@dotgov/core
Version:
DGS core.
110 lines • 13.6 kB
JavaScript
import { ComponentFactoryResolver, Inject, Injectable, ReflectiveInjector, } from '@angular/core';
export class FactoryService {
constructor(resolver, environment = {}) {
this.resolver = resolver;
this.environment = environment;
this.debug = Boolean(this.environment.debug);
}
/**
* How to use:
* // html
* <div #container></div>
* // class
* @ViewChild('container', { read: ViewContainerRef }) container;
* // ngAfterViewInit
* const factory = this.factoryService.componentByName('ComponentName');
* this.container.createComponent(factory);
* this.ref.detectChanges();
*
* @param componentName
*/
componentByName(componentName, target, inputs) {
const factories = Array.from(this.resolver['_factories'].keys());
const factoryClass = factories.find((x) => x.name === componentName);
if (!factoryClass) {
if (this.debug) {
console.warn(`Could not load ${componentName}`);
}
return;
}
return this.createComponent(factoryClass, inputs, target);
}
/**
* How to use:
* // html
* <div #container></div>
* // class
* @ViewChild('container', { read: ViewContainerRef }) container;
* // ngAfterViewInit
* const factory = this.factoryService.componentbySelector('component-selector');
* this.container.createComponent(factory);
* this.ref.detectChanges();
*
* @param componentName
*/
componentbySelector(componentSelector, componentFactories, target, inputs = {}) {
if (!componentSelector) {
if (this.debug) {
console.warn('Started client-control with no target component.');
}
return FactoryService.NOT_FOUND;
}
let res;
componentFactories.forEach((value) => {
if (value && value.selector === componentSelector) {
res = this.createComponent(value.factoryClass, inputs, target);
return;
}
});
if (!res) {
if (this.debug) {
console.warn(`Could not load ${componentSelector}`);
}
return FactoryService.NOT_FOUND;
}
if (!res.create) {
return FactoryService.HAS_ROUTE;
}
return res;
}
createComponent(factoryClass, inputs, target) {
if (!target || !target.insert) {
if (this.debug) {
console.warn(`Could not get target for `, factoryClass, '|', target);
}
return FactoryService.NOT_FOUND;
}
if (!factoryClass) {
if (this.debug) {
console.warn(`Could not load factory class`);
}
return FactoryService.NOT_FOUND;
}
const inputProviders = Object.keys(inputs).map(inputName => {
return { provide: inputName, useValue: inputs[inputName] };
});
const resolvedInputs = ReflectiveInjector.resolve(inputProviders);
// We create an injector out of the data we want to pass down and this components injector
const injector = ReflectiveInjector.fromResolvedProviders(resolvedInputs, target.parentInjector);
// We create a factory out of the component we want to create
const factory = this.resolver.resolveComponentFactory(factoryClass);
// We create the component using the factory and the injector
const component = factory.create(injector);
// We insert the component into the dom container
target.insert(component.hostView);
Object.keys(inputs).forEach(input => {
component.instance[input] = inputs[input];
});
return component;
}
}
FactoryService.HAS_ROUTE = null;
FactoryService.NOT_FOUND = undefined;
FactoryService.decorators = [
{ type: Injectable }
];
FactoryService.ctorParameters = () => [
{ type: ComponentFactoryResolver },
{ type: undefined, decorators: [{ type: Inject, args: ['environment',] }] }
];
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmFjdG9yeS5zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2xpYi9zZXJ2aWNlcy9mYWN0b3J5LnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUNMLHdCQUF3QixFQUV4QixNQUFNLEVBQ04sVUFBVSxFQUNWLGtCQUFrQixHQUVuQixNQUFNLGVBQWUsQ0FBQztBQUl2QixNQUFNLE9BQU8sY0FBYztJQU16QixZQUNVLFFBQWtDLEVBQ1gsY0FBK0IsRUFBRTtRQUR4RCxhQUFRLEdBQVIsUUFBUSxDQUEwQjtRQUNYLGdCQUFXLEdBQVgsV0FBVyxDQUFzQjtRQUVoRSxJQUFJLENBQUMsS0FBSyxHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQy9DLENBQUM7SUFFRDs7Ozs7Ozs7Ozs7O09BWUc7SUFDSCxlQUFlLENBQUMsYUFBcUIsRUFBRSxNQUFNLEVBQUUsTUFBYztRQUMzRCxNQUFNLFNBQVMsR0FBRyxLQUFLLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsWUFBWSxDQUFDLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQztRQUNqRSxNQUFNLFlBQVksR0FBYyxTQUFTLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBTSxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsSUFBSSxLQUFLLGFBQWEsQ0FBQyxDQUFDO1FBRXJGLElBQUksQ0FBQyxZQUFZLEVBQUU7WUFDakIsSUFBSSxJQUFJLENBQUMsS0FBSyxFQUFFO2dCQUNkLE9BQU8sQ0FBQyxJQUFJLENBQUMsa0JBQWtCLGFBQWEsRUFBRSxDQUFDLENBQUM7YUFDakQ7WUFDRCxPQUFPO1NBQ1I7UUFFRCxPQUFPLElBQUksQ0FBQyxlQUFlLENBQUMsWUFBWSxFQUFFLE1BQU0sRUFBRSxNQUFNLENBQUMsQ0FBQztJQUM1RCxDQUFDO0lBRUQ7Ozs7Ozs7Ozs7OztPQVlHO0lBQ0gs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bkhNLHdCQUFTLEdBQUcsSUFBSSxDQUFDO0FBQ2pCLHdCQUFTLEdBQUcsU0FBUyxDQUFDOztZQUg5QixVQUFVOzs7WUFUVCx3QkFBd0I7NENBa0JyQixNQUFNLFNBQUMsYUFBYSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XHJcbiAgQ29tcG9uZW50RmFjdG9yeVJlc29sdmVyLFxyXG4gIENvbXBvbmVudFJlZixcclxuICBJbmplY3QsXHJcbiAgSW5qZWN0YWJsZSxcclxuICBSZWZsZWN0aXZlSW5qZWN0b3IsXHJcbiAgVHlwZSxcclxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuaW1wb3J0IHsgSURHU0Vudmlyb25tZW50IH0gZnJvbSAnLi4vbW9kZWxzL2Vudmlyb25tZW50JztcclxuXHJcbkBJbmplY3RhYmxlKClcclxuZXhwb3J0IGNsYXNzIEZhY3RvcnlTZXJ2aWNlIHtcclxuICBzdGF0aWMgSEFTX1JPVVRFID0gbnVsbDtcclxuICBzdGF0aWMgTk9UX0ZPVU5EID0gdW5kZWZpbmVkO1xyXG5cclxuICBwcml2YXRlIGRlYnVnOiBib29sZWFuO1xyXG5cclxuICBjb25zdHJ1Y3RvcihcclxuICAgIHByaXZhdGUgcmVzb2x2ZXI6IENvbXBvbmVudEZhY3RvcnlSZXNvbHZlcixcclxuICAgIEBJbmplY3QoJ2Vudmlyb25tZW50JykgcHJpdmF0ZSBlbnZpcm9ubWVudDogSURHU0Vudmlyb25tZW50ID0ge30sXHJcbiAgKSB7XHJcbiAgICB0aGlzLmRlYnVnID0gQm9vbGVhbih0aGlzLmVudmlyb25tZW50LmRlYnVnKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEhvdyB0byB1c2U6XHJcbiAgICogLy8gaHRtbFxyXG4gICAqIDxkaXYgI2NvbnRhaW5lcj48L2Rpdj5cclxuICAgKiAvLyBjbGFzc1xyXG4gICAqIEBWaWV3Q2hpbGQoJ2NvbnRhaW5lcicsIHsgcmVhZDogVmlld0NvbnRhaW5lclJlZiB9KSBjb250YWluZXI7XHJcbiAgICogLy8gbmdBZnRlclZpZXdJbml0XHJcbiAgICogY29uc3QgZmFjdG9yeSA9IHRoaXMuZmFjdG9yeVNlcnZpY2UuY29tcG9uZW50QnlOYW1lKCdDb21wb25lbnROYW1lJyk7XHJcbiAgICogdGhpcy5jb250YWluZXIuY3JlYXRlQ29tcG9uZW50KGZhY3RvcnkpO1xyXG4gICAqIHRoaXMucmVmLmRldGVjdENoYW5nZXMoKTtcclxuICAgKlxyXG4gICAqIEBwYXJhbSBjb21wb25lbnROYW1lXHJcbiAgICovXHJcbiAgY29tcG9uZW50QnlOYW1lKGNvbXBvbmVudE5hbWU6IHN0cmluZywgdGFyZ2V0LCBpbnB1dHM6IG9iamVjdCk6IENvbXBvbmVudFJlZjxhbnk+IHtcclxuICAgIGNvbnN0IGZhY3RvcmllcyA9IEFycmF5LmZyb20odGhpcy5yZXNvbHZlclsnX2ZhY3RvcmllcyddLmtleXMoKSk7XHJcbiAgICBjb25zdCBmYWN0b3J5Q2xhc3MgPSA8VHlwZTxhbnk+PmZhY3Rvcmllcy5maW5kKCh4OiBhbnkpID0+IHgubmFtZSA9PT0gY29tcG9uZW50TmFtZSk7XHJcblxyXG4gICAgaWYgKCFmYWN0b3J5Q2xhc3MpIHtcclxuICAgICAgaWYgKHRoaXMuZGVidWcpIHtcclxuICAgICAgICBjb25zb2xlLndhcm4oYENvdWxkIG5vdCBsb2FkICR7Y29tcG9uZW50TmFtZX1gKTtcclxuICAgICAgfVxyXG4gICAgICByZXR1cm47XHJcbiAgICB9XHJcblxyXG4gICAgcmV0dXJuIHRoaXMuY3JlYXRlQ29tcG9uZW50KGZhY3RvcnlDbGFzcywgaW5wdXRzLCB0YXJnZXQpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogSG93IHRvIHVzZTpcclxuICAgKiAvLyBodG1sXHJcbiAgICogPGRpdiAjY29udGFpbmVyPjwvZGl2PlxyXG4gICAqIC8vIGNsYXNzXHJcbiAgICogQFZpZXdDaGlsZCgnY29udGFpbmVyJywgeyByZWFkOiBWaWV3Q29udGFpbmVyUmVmIH0pIGNvbnRhaW5lcjtcclxuICAgKiAvLyBuZ0FmdGVyVmlld0luaXRcclxuICAgKiBjb25zdCBmYWN0b3J5ID0gdGhpcy5mYWN0b3J5U2VydmljZS5jb21wb25lbnRieVNlbGVjdG9yKCdjb21wb25lbnQtc2VsZWN0b3InKTtcclxuICAgKiB0aGlzLmNvbnRhaW5lci5jcmVhdGVDb21wb25lbnQoZmFjdG9yeSk7XHJcbiAgICogdGhpcy5yZWYuZGV0ZWN0Q2hhbmdlcygpO1xyXG4gICAqXHJcbiAgICogQHBhcmFtIGNvbXBvbmVudE5hbWVcclxuICAgKi9cclxuICBjb21wb25lbnRieVNlbGVjdG9yKGNvbXBvbmVudFNlbGVjdG9yOiBzdHJpbmcsIGNvbXBvbmVudEZhY3Rvcmllczoge3NlbGVjdG9yOnN0cmluZywgZmFjdG9yeUNsYXNzOiBhbnl9W10gLCB0YXJnZXQsIGlucHV0czogb2JqZWN0ID0ge30pOiBDb21wb25lbnRSZWY8YW55PiB7XHJcbiAgICBpZiAoIWNvbXBvbmVudFNlbGVjdG9yKSB7XHJcbiAgICAgIGlmICh0aGlzLmRlYnVnKSB7XHJcbiAgICAgICAgY29uc29sZS53YXJuKCdTdGFydGVkIGNsaWVudC1jb250cm9sIHdpdGggbm8gdGFyZ2V0IGNvbXBvbmVudC4nKTtcclxuICAgICAgfVxyXG4gICAgICByZXR1cm4gRmFjdG9yeVNlcnZpY2UuTk9UX0ZPVU5EO1xyXG4gICAgfVxyXG4gICAgbGV0IHJlcztcclxuICAgIGNvbXBvbmVudEZhY3Rvcmllcy5mb3JFYWNoKCh2YWx1ZSkgPT4ge1xyXG4gICAgICBpZiAodmFsdWUgJiYgdmFsdWUuc2VsZWN0b3IgPT09IGNvbXBvbmVudFNlbGVjdG9yKSB7XHJcbiAgICAgICAgcmVzID0gdGhpcy5jcmVhdGVDb21wb25lbnQodmFsdWUuZmFjdG9yeUNsYXNzLCBpbnB1dHMsIHRhcmdldCk7XHJcbiAgICAgICAgcmV0dXJuO1xyXG4gICAgICB9XHJcbiAgICB9KTtcclxuICAgIGlmICghcmVzKSB7XHJcbiAgICAgIGlmICh0aGlzLmRlYnVnKSB7XHJcbiAgICAgICAgY29uc29sZS53YXJuKGBDb3VsZCBub3QgbG9hZCAke2NvbXBvbmVudFNlbGVjdG9yfWApO1xyXG4gICAgICB9XHJcbiAgICAgIHJldHVybiBGYWN0b3J5U2VydmljZS5OT1RfRk9VTkQ7XHJcbiAgICB9XHJcbiAgICBpZiAoIXJlcy5jcmVhdGUpIHtcclxuICAgICAgcmV0dXJuIEZhY3RvcnlTZXJ2aWNlLkhBU19ST1VURTtcclxuICAgIH1cclxuICAgIHJldHVybiByZXM7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGNyZWF0ZUNvbXBvbmVudChmYWN0b3J5Q2xhc3MsIGlucHV0cywgdGFyZ2V0KTogQ29tcG9uZW50UmVmPGFueT4ge1xyXG4gICAgaWYgKCF0YXJnZXQgfHwgIXRhcmdldC5pbnNlcnQpIHtcclxuICAgICAgaWYgKHRoaXMuZGVidWcpIHtcclxuICAgICAgICBjb25zb2xlLndhcm4oYENvdWxkIG5vdCBnZXQgdGFyZ2V0IGZvciBgLCBmYWN0b3J5Q2xhc3MsICd8JywgdGFyZ2V0KTtcclxuICAgICAgfVxyXG4gICAgICByZXR1cm4gRmFjdG9yeVNlcnZpY2UuTk9UX0ZPVU5EO1xyXG4gICAgfVxyXG4gICAgaWYgKCFmYWN0b3J5Q2xhc3MpIHtcclxuICAgICAgaWYgKHRoaXMuZGVidWcpIHtcclxuICAgICAgICBjb25zb2xlLndhcm4oYENvdWxkIG5vdCBsb2FkIGZhY3RvcnkgY2xhc3NgKTtcclxuICAgICAgfVxyXG4gICAgICByZXR1cm4gRmFjdG9yeVNlcnZpY2UuTk9UX0ZPVU5EO1xyXG4gICAgfVxyXG5cclxuICAgIGNvbnN0IGlucHV0UHJvdmlkZXJzID0gT2JqZWN0LmtleXMoaW5wdXRzKS5tYXAoaW5wdXROYW1lID0+IHtcclxuICAgICAgcmV0dXJuIHsgcHJvdmlkZTogaW5wdXROYW1lLCB1c2VWYWx1ZTogaW5wdXRzW2lucHV0TmFtZV0gfTtcclxuICAgIH0pO1xyXG4gICAgY29uc3QgcmVzb2x2ZWRJbnB1dHMgPSBSZWZsZWN0aXZlSW5qZWN0b3IucmVzb2x2ZShpbnB1dFByb3ZpZGVycyk7XHJcblxyXG4gICAgLy8gV2UgY3JlYXRlIGFuIGluamVjdG9yIG91dCBvZiB0aGUgZGF0YSB3ZSB3YW50IHRvIHBhc3MgZG93biBhbmQgdGhpcyBjb21wb25lbnRzIGluamVjdG9yXHJcbiAgICBjb25zdCBpbmplY3RvciA9IFJlZmxlY3RpdmVJbmplY3Rvci5mcm9tUmVzb2x2ZWRQcm92aWRlcnMoXHJcbiAgICAgIHJlc29sdmVkSW5wdXRzLFxyXG4gICAgICB0YXJnZXQucGFyZW50SW5qZWN0b3IsXHJcbiAgICApO1xyXG5cclxuICAgIC8vIFdlIGNyZWF0ZSBhIGZhY3Rvcnkgb3V0IG9mIHRoZSBjb21wb25lbnQgd2Ugd2FudCB0byBjcmVhdGVcclxuICAgIGNvbnN0IGZhY3RvcnkgPSB0aGlzLnJlc29sdmVyLnJlc29sdmVDb21wb25lbnRGYWN0b3J5KGZhY3RvcnlDbGFzcyk7XHJcblxyXG4gICAgLy8gV2UgY3JlYXRlIHRoZSBjb21wb25lbnQgdXNpbmcgdGhlIGZhY3RvcnkgYW5kIHRoZSBpbmplY3RvclxyXG4gICAgY29uc3QgY29tcG9uZW50ID0gZmFjdG9yeS5jcmVhdGUoaW5qZWN0b3IpO1xyXG5cclxuICAgIC8vIFdlIGluc2VydCB0aGUgY29tcG9uZW50IGludG8gdGhlIGRvbSBjb250YWluZXJcclxuICAgIHRhcmdldC5pbnNlcnQoY29tcG9uZW50Lmhvc3RWaWV3KTtcclxuICAgIE9iamVjdC5rZXlzKGlucHV0cykuZm9yRWFjaChpbnB1dCA9PiB7XHJcbiAgICAgIGNvbXBvbmVudC5pbnN0YW5jZVtpbnB1dF0gPSBpbnB1dHNbaW5wdXRdO1xyXG4gICAgfSk7XHJcbiAgICByZXR1cm4gY29tcG9uZW50O1xyXG4gIH1cclxufVxyXG4iXX0=