Search code examples
javascriptangularangular7angular8

ngDestroy lifecycle is not Triggering in dynamically created Angular component


ngDestroy lifecycle method is not triggering for dynamically created component. I'm creating multiple component dynamically using ComponentFactoryResolver.

In my dynamically created component I'm fetching some data from API and I'm periodically fetching the data for every 5 mins using setInterval method. and I'm clearing the Interval instance inside ngDestroy method , while redirecting to different page, the component's ngDestroy is not triggering and the API is triggering even the component is not in the view.

This is how I'm creating components dynamically.

    const factory = this.resolver.resolveComponentFactory(DynamicComponent); // Component Construction
    const ref = factory.create(this.injector);

Here is my DynamicComponent which has the functionalities

import { Component, OnInit, OnDestroy } from "@angular/core";

@Component({
  selector: "app-dynamic,
  templateUrl: "./dynamic.component.html",
  styleUrls: ["./dynamic.component.scss"]
})
export class DynamicComponent implements OnInit, OnDestroy {
  loopCount: number;
  autoRefreshInterval: any;
  constructor() {}

  ngOnInit() {
    this.fetchData();
    this.startAutoRefreshLoop();
  }

  ngOnDestroy(): void {
    console.log("Destroying loop"); // ngOnDestroy is not triggering
    this.clearAutoRefreshLoop();
  }

  clearAutoRefreshLoop() {
    clearInterval(this.autoRefreshInterval);
  }

  /*
    function for starting the Automatically recall the service for certain period of time
  */
  startAutoRefreshLoop() {
    console.log("starting loop");
    this.loopCount = 10 * 1000;
    this.autoRefreshInterval = setInterval(() => {
      this.fetchData();
    }, this.loopCount);
  }

  fetchData() {
    // FETCHING DATA FROM API CODE ....
  }
}


Solution

  • You need to destroy the dynamically loaded component by manually calling : this.componentRef.destroy(); to trigger ngOndestroy()

    Example :

    import {
        Component,
        ViewChild,
        ViewContainerRef,
        ComponentFactoryResolver,
        ComponentRef,
        ComponentFactory
    } from '@angular/core';
    import { DynamicComponent } from './dynamic.component';
    @Component({
        selector: 'app-root',
        templateUrl: './app.component.html'
    })
    export class AppComponent {
        title = 'app';
        componentRef: any;
        @ViewChild('container', { read: ViewContainerRef }) entry: ViewContainerRef;
        constructor(private resolver: ComponentFactoryResolver) { }
        createComponent(message) {
            this.entry.clear();
            const factory = this.resolver.resolveComponentFactory(DynamicComponent); 
            this.componentRef = this.entry.createComponent(factory);
        }
        destroyComponent() {
            this.componentRef.destroy(); // you need to call this
        }
    }
    

    For more information : how-to-dynamically-create-a-component-in-angular