Angular: ngOnInit hook does not works in dynamically created component

  angular, javascript

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.

  1. If I remove ref.instance.ngOnInit() call in AddingDirective, I do not get in ngOnInit of DynamicComponent (debugger and console.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?
  2. 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?
  3. Is there a better way to assing inputs than doing Object.assign(ref.instance, inputs) as above?

PS. I’m using Angular 11

Source: Angular Questions

One Reply to “Angular: ngOnInit hook does not works in dynamically created component”

  • I’m having a similar issue within a dialog. I only render a chart component when the data is there to render the chart, using *ngIf. When the data gets set, the component is added to the HTML output, but the OnInit never fires. I’m on Angular 10 for this app.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.