Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 6: ViewContainerRef.createComponent with custom provider

Tags:

angular

My Angular 6 service creates a component dynamically:

buildComponent(viewContainerRef) {
  const factory = this.componentFactoryResolver.resolveComponentFactory(MyComponent);
  const componentRef = viewContainerRef.createComponent(componentFactory);
  ...
}

The component I'm creating needs a handle to viewContainerRef in its constructor. How can I pass it from the service while I create the component? Is there a way to perhaps customize the injector that is used when createComponent executes? (hint: I notice that injector is one of the params to createComponent)

I have tried to pass the container to the component on the next line, with something like:

componentRef.instance.viewContainer = viewContainerRef;

This doesn't work for me though because I need the container reference to be available immediately upon construction if possible.

like image 673
BeetleJuice Avatar asked Dec 02 '25 09:12

BeetleJuice


1 Answers

I succeeded by creating a custom injector and providing it as the 3rd param to viewContainerRef.createComponent. Here is my service code:

constructor(
  private injector: Injector, 
  private componentFactoryResolver: ComponentFactoryResolver) {}

buildComponent(viewContainerRef) {
  const inj: Injector = this.makeCustomInjector(viewContainerRef);
  const factory = this.componentFactoryResolver.resolveComponentFactory(MyComponent);
  const componentRef = viewContainerRef.createComponent(componentFactory, undefined, inj);
}

makeCustomInjector(viewContainerRef) {
  return Injector.create({
    providers: [{provide: ViewContainerRef, useValue: viewContainer}],
    parent: this.injector
  });
}

Now the MyComponent parent Injector has the viewContainerRef I want. The final step, to be able to inject that view container into the component, is to tell the component to ignore its own injector and take from its parent. This is the MyComponent constructor:

constructor(@SkipSelf() viewContainerRef: ViewContainerRef){}

SkipSelf comes from @angular/core

like image 192
BeetleJuice Avatar answered Dec 05 '25 07:12

BeetleJuice



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!