I'm having the following directive that adds dynamic component to ng-container
@Directive({
selector: '[appAddingDirective]'
})
export class AddingDirective {
constructor(protected vc: ViewContainerRef) { }
public addComponent(factory: ComponentFactory<any>, inputs: any): void {
this.vc.clear();
const ref: ComponentRef<any> = this.vc.createComponent(factory);
Object.assign(ref.instance, inputs); // can't find more elegant way to assign inputs((
ref.instance.ngOnInit(); // IMPORTANT: if I remove this call ngOnInit will not be called
}
}
The directive is used in an obvious way.
@Component({
selector: 'app-wrapper',
template: `<ng-container appAddingDirective></ng-container>`
})
export class WrapperComponent implements AfterViewInit{
@ViewChild(DynamicItemDirective)
private dynamicItem: DynamicItemDirective;
constructor() { }
ngAfterViewInit(): void {
// hope it doesn't matter how we get componentFactory
this.dynamicItem.addComponent(componentFactory, {a: '123'});
}
}
Finally in a component that is loaded dynamically I have
@Component({
selector: 'app-dynamic',
template: '<p>Dynamic load works {{ a }}</p>'
})
export class DynamicComponent implements OnInit {
@Input() a: string;
constructor() {}
ngOnInit(): void {
console.log(this.a);
debugger;
}
}
Here are my questions.
- If I remove
ref.instance.ngOnInit()
call inAddingDirective
, I do not get inngOnInit
ofDynamicComponent
(debugger
andconsole.log
do not fire up). Do component lifecycle hooks work in a component that is created and attached dynamically? What is the best way to make these hooks work? - I don't see rendered string
Dynamic load works 123
still if I remove{{ a }}
in template (template: '<p>Dynamic load works</p>'
),Dynamic load works
is rendered as it should. What is the reason and how can I fix that? - Is there a better way to assing inputs than doing
Object.assign(ref.instance, inputs)
as above?
PS. I'm using Angular 11