0
votes

I'm trying to resolve a simple task: dynamically load a component contains a form control. Everything is OK except I get such error:

ERROR Error: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'undefined'. Current value: '[object Object]'. It seems like the view has been created after its parent and its children have been dirty checked. Has it been created in a change detection hook?

I load a component in a canonical way - in ngAfterViewInit hook with a ComponentFactoryResolver and a ViewContainerRef.

I've tried to google about this problem and search here, but I didn't found any clear explanation why it is and how I can fix it.

I'm new in Angular and I might ask questions in a wrong way.

I've prepared an example about it

Thanks in advance!

1
Why you commented out this part <!--<app-my-form></app-my-form>--> un-comment and use it this is the best approach - Kamran Khatti
@KamranKhatti Hi, Thanks a lot for your answer! But it would be the best soulution, if I don't need to load a component dynamically from vague number of components. - Alexander KLimov
@Indraraj26 Thanks a lot for this link! It helped me with my trouble. P.S.: it's really strange for me, that in the Angular docs (angular.io/guide/dynamic-component-loader) said nothing about that. - Alexander KLimov

1 Answers

0
votes

Actually I am not sure why that kind of error is coming, however setTimeout can solve your problem.

setTimeout(() => {
      let factory = this.compFactoryResolver.resolveComponentFactory(MyFormComponent);
      let compRef = this.formSlotRef.createComponent(factory);
});

Another way is to use OnPush change detection strategy. It will not detect your change automatically but you will trigger the detection after the view is checked and your component is added.

@Component({
  selector: "my-app",
  templateUrl: "./app.component.html",
  styleUrls: ["./app.component.css"],
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class AppComponent {
  name = "Angular " + VERSION.major;

  @ViewChild("formSlot", { read: ViewContainerRef })
  private formSlotRef: ViewContainerRef;

  constructor(
    private compFactoryResolver: ComponentFactoryResolver,
    private cdr: ChangeDetectorRef
  ) {}

  ngAfterViewInit() {
    let factory = this.compFactoryResolver.resolveComponentFactory(
      MyFormComponent
    );
    let compRef = this.formSlotRef.createComponent(factory);
    this.cdr.detectChanges();
  }
}