Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cannot read property 'viewContainerRef' of undefined

I am trying to display a dynamic component similar (not exact) to the example in angular docs.

I have a dynamic directive with viewContainerRef

@Directive({
   selector: '[dynamicComponent]'
})
export class DynamicComponentDirective {
   constructor(public viewContainerRef: ViewContainerRef) { }
}

Excerpt from component code

@ViewChild(DynamicComponentDirective) adHost: DynamicComponentDirective;
..
ngAfterViewInit() {
let componentFactory = null;
                console.log(component);
                componentFactory = this.componentFactoryResolver.resolveComponentFactory(component);
                // this.adHost.viewContainerRef.clear();
                const viewContainerRef = this.adHost.viewContainerRef;
                viewContainerRef.createComponent(componentFactory);
}

Finally added <ng-template dynamicComponent></ng-template> in template

like image 416
mperle Avatar asked Jan 18 '18 21:01

mperle


People also ask

Why is ViewContainerRef undefined?

You see this error when the directive does not construct. You can set a breakpoint on the directive's constructor and check if the breakpoint ever hits. If not, that means that you are not loading the directive correctly.

What is ViewContainerRef?

ViewContainerRef represents a container where one or more views can be attached. The first thing to mention here is that any DOM element can be used as a view container. What's interesting is that Angular doesn't insert views inside the element, but appends them after the element bound to ViewContainer .


3 Answers

You can take this approach: don't create directive, instead give an Id to ng-template

<ng-template #dynamicComponent></ng-template>

use @ViewChild decorator inside your component class

@ViewChild('dynamicComponent', { read: ViewContainerRef }) myRef

ngAfterViewInit() {
    const factory = this.componentFactoryResolver.resolveComponentFactory(component);
    const ref = this.myRef.createComponent(factory);
    ref.changeDetectorRef.detectChanges();
}
like image 149
Rohit Sharma Avatar answered Oct 20 '22 21:10

Rohit Sharma


I had the same problem. You have to add the directive into the AppModule:

 @NgModule({
  declarations: [
    AppComponent,
    ...,
    YourDirective,
  ],
  imports: [
   ...
  ],
  providers: [...],
  bootstrap: [AppComponent],
  entryComponents: [components to inject if required]
})
like image 38
Michael Avatar answered Oct 20 '22 21:10

Michael


In Angular 8 my fix was:

@ViewChild('dynamicComponent', {static: true, read: ViewContainerRef}) container: ViewContainerRef;
like image 18
sampereless Avatar answered Oct 20 '22 21:10

sampereless