I\'m trying to dynamically create and show component and i need to pass some data into it, so that it knows what to show.
Here is my code:
html part:
Hey there change widgets to widgets = [], otherwise angular will keep calling the method in the ngFor loop. If you console log in the constructor for the component you find this is happening.
If you open code of NgComponentOutlet
directive:
@Directive({selector: '[ngComponentOutlet]'})
export class NgComponentOutlet implements OnChanges, OnDestroy {
@Input() ngComponentOutlet: Type<any>;
@Input() ngComponentOutletInjector: Injector;
you can notice that it takes ngComponentOutlet
input that should have type Type<any>
but you're passing object to it.
Also we can see that this directive can take Injector
as @Input
. So lets leverage this knowledge to do your task.
For example we wrote template like:
<ng-container *ngComponentOutlet="component; injector: injector"></ng-container>
Now lets declare component
and injector
properties in component class:
@Component({...})
export class AppComponent {
component: Type<any>;
injector: Injector;
constructor(private inj: Injector) {}
ngOnInit() {
this.component = ProjectComponent; // note: we're passing type here
this.injector = Injector.create([
{ provide: BasicProject, useValue: new Project('test name') }
], this.inj);
}
}
and your ProjectComponent
now uses angular DI mechanism to get data we passed to injector:
export class ProjectComponent {
name: string;
constructor(project: BasicProject) {
this.name = project.name;
}
}
Stackblitz Example
Thanks to yuzui's comment I managed to get something working
The full runnable code can be found on Stackblitz
export class AppComponent {
name = 'Dynamic components in Angular 5';
private injectors = {};
constructor(private inj: Injector) {
}
get widgets() {
return [
{id: 1, widgetType:'child-component', settings: { showSecondLine: false} },
{id: 2, widgetType:'child2-component', settings: { text: 'helloooooooooo'} },
];
}
getComponent(config: WidgetConfiguration) {
switch (config.widgetType) {
case 'child-component':
return ChildComponent;
case 'child2-component':
return Child2Component;
}
}
getInjector(config: WidgetConfiguration) {
let inject = this.injectors[config.id];
if (!inject) {
inject = Injector.create([
{ provide: GeneralSettings, useValue: config.settings }
], this.inj);
this.injectors[config.id] = inject;
}
return inject;
}
}