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:
<div class="basicContainer">
<div class="projectsTreeContainer">
<input type="text" id="searchWord" placeholder="Search through projects"/>
<button (click)="loadAddProject()">Add new Project</button>
<app-projects-tree (onLoadProjectDetails)="loadProjectDetails($event)"
(onLoadWpDetails)="loadWpDetails($event)"
(onSelectAndLoadJobDetails)="loadJobDetails($event)"></app-projects-tree>
</div>
<div class="infoContainer">
<ng-container *ngComponentOutlet="details"></ng-container>
</div>
</div>
Components:
export class ProjectsComponent implements OnInit {
details: Component;
private showWp: boolean;
constructor() {
}
loadProjectDetails(project: BasicProject): void {
this.details = new ProjectComponent(project);
}
and the component i want dynamically create and show:
export class ProjectComponent implements OnInit {
project: Project;
constructor(basicProject: BasicProject) {
this.project = new Project();
this.project.name = basicProject.name ;
}
NgModule:
@NgModule({
declarations: [
AppComponent,
NavbarComponent,
LoginComponent,
ProjectsComponent,
ProjectComponent,
ProjectsTreeComponent,
TreeProjectComponent,
TreeWpComponent,
WpComponent,
JobComponent,
AddProjectComponent
],
imports: [
BrowserModule,
FormsModule,
RouterModule.forRoot(
AppRoutes.appRoutes,
// {enableTracing: true} // <-- debugging purposes only
),
HttpClientModule,
HttpModule
],
providers: [
AuthenticationService,
ProjectsService,
CanActivateAuthGuard,
{
provide: HTTP_INTERCEPTORS,
useClass: AuthInterceptor,
multi: true
}],
bootstrap: [AppComponent],
entryComponents: [ProjectComponent, WpComponent, JobComponent, AddProjectComponent]
})
The error message:
ProjectsComponent.html:15 ERROR Error: No component factory found for [object Object].
How can i do the task? Thanks.
If you open the 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;
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With