0

I'm using Angular 6 and I want to implement the dynamic addition of components according to the instructions, but I get an error: "Cannot read property 'create' of undefined."

component.html

<mat-card>
  <mat-card-header>
    <mat-card-title>...</mat-card-title>
  </mat-card-header>
  <mat-card-content>
    <ng-template answerHost></ng-template>
  </mat-card-content>
</mat-card>

component.ts

@ViewChild(AnswerHostDirective) answerHost: AnswerHostDirective;
private stepAnswerType1: ComponentFactory<StepAnswerType1Component>;
private stepAnswerType2: ComponentFactory<StepAnswerType2Component>;
private stepAnswerType3: ComponentFactory<StepAnswerType3Component>;

/* ... */

changeStep(id: number) {
    let viewContainerRef = this.answerHost.viewContainerRef;

    let componentRef;
    if (this.step.type == 1) {
      componentRef = viewContainerRef.createComponent(this.stepAnswerType1);
    }
    if (this.step.type == 2) {
      componentRef = viewContainerRef.createComponent(this.stepAnswerType2);
    }
    if (this.step.type == 3) {
      componentRef = viewContainerRef.createComponent(this.stepAnswerType3);
    }
}

directive

import { Directive, ViewContainerRef } from '@angular/core';

@Directive({
  selector: '[answerHost]'
})
export class AnswerHostDirective {

  constructor(public viewContainerRef: ViewContainerRef) { }

}

I tried to replace the directive with a reference to the component's id, but I get the same error. component.html

<mat-card>
  <mat-card-header>
    <mat-card-title>...</mat-card-title>
  </mat-card-header>
  <mat-card-content>
    <ng-template #answerContainer></ng-template>
  </mat-card-content>
</mat-card>

component.ts

@ViewChild('answerContainer', { read: ViewContainerRef }) answerContainer: ViewContainerRef;
private stepAnswerType1: ComponentFactory<StepAnswerType1Component>;
private stepAnswerType2: ComponentFactory<StepAnswerType2Component>;
private stepAnswerType3: ComponentFactory<StepAnswerType3Component>;

/* ... */

changeStep(id: number) {
    if (this.step.type == 1) {
      componentRef = this.answerContainer.createComponent(this.stepAnswerType1);
    }
    if (this.step.type == 2) {
      componentRef = this.answerContainer.createComponent(this.stepAnswerType2);
    }
    if (this.step.type == 3) {
      componentRef = this.answerContainer.createComponent(this.stepAnswerType3);
    }
}

What could be the problem?

Fixed I updated part of the code. component.ts

import { StepAnswerType1Component } from './step-answer-type1/step-answer-type1.component';
import { StepAnswerType2Component } from './step-answer-type2/step-answer-type2.component';
import { StepAnswerType3Component } from './step-answer-type3/step-answer-type3.component';

/* some code */

@ViewChild('answerContainer', { read: ViewContainerRef }) answerContainer: ViewContainerRef;

/* some code */

changeStep(id: number) {
    let componentRef, componentFactory;
    if (this.step.type == 1) {
      componentFactory = this.componentFactoryResolver.resolveComponentFactory(StepAnswerType1Component);
    }
    if (this.step.type == 2) {
      componentFactory = this.componentFactoryResolver.resolveComponentFactory(StepAnswerType2Component);
    }
    if (this.step.type == 3) {
      componentFactory = this.componentFactoryResolver.resolveComponentFactory(StepAnswerType3Component);
    }
    componentRef = viewContainerRef.createComponent(componentFactory);
 }
2
  • Try changing ng-template with ng-container Commented Sep 28, 2018 at 7:45
  • The same mistake. Commented Sep 28, 2018 at 9:15

1 Answer 1

1

Make sure you are calling this method 'changeStep' inside 'ngAfterViewInit()'.

Sign up to request clarification or add additional context in comments.

6 Comments

I tried to call the method changeStep from ngOninit and ngAfterViewInit. The result is the same.
created a stack overflow and its working fine. stackblitz.com/edit/angular-material-with-angular-v5-eefxju
Notice I'm using createComponent and Angular 6. Your example is CreativeEmbededViev and Angular 2.
I am able to access all the public Method available for ViewContainerRef Instance Class. i.e clear(), createEmbeddedView(). Also createComponent() will also work.
I have updated stackblitz with createComponent method
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.