angulardependency-injectiondynamically-generatedapplication-lifecycleangular-injector

Angular2: Are dynamically created injectors (created via Injector.create(...)) ever destroyed?


Need some comments on the lifecycle of injectors created with Injector.create method

I tried to create a component via ViewContainerRef.createComponent(...) and provide dynamically generated dependencies using a custom injector that was passed in arguments. That injector had a parent injector inherited from the host component.

When after some time I destroyed that component, I noticed that the services I had provided in the dynamic injector didn't execute the ngOnDestroy method.

Nevertheless, all the services provided via @Component decorator (in the parent component) were successfully destroyed (in fact, they're always destroyed this way).

What can be the reason of such behaviour? Is there a way to destroy dynamically created injectors?

Here's an StackBlitz example: https://stackblitz.com/edit/stackblitz-starters-vstiqn

When I close the parent component via the toggle button, I expect that the ChildService would call ngOnDestroy method as the ParentService does.


Solution

  • The best way to destroy an Injector manually is to go with an EnvironmentInjector which has the destroy method.

    With your example that would be :

    export class ParentComponent implements OnInit, OnDestroy {
      myInjector?:EnvironmentInjector
    
      constructor(
        private readonly viewContainerRef: ViewContainerRef,
        private readonly environmentInjector: EnvironmentInjector,
        private readonly parentService: ParentService
      ) {}
    
      ngOnInit() {
        this.myInjector = createEnvironmentInjector( [ChildService],
          this.environmentInjector,
        ); // create
    
        this.viewContainerRef.createComponent(ChildComponent, {
          injector: this.myInjector,
        });
      }
    
      ngOnDestroy() {
        this.myInjector?.destroy() // destroy
        console.log('ParentComponent destroyed'); 
      }
    }