0

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!

derloopkat
  • 6,232
  • 16
  • 38
  • 45
  • Why you commented out this part `` un-comment and use it this is the best approach – Kamran Khatti Aug 08 '20 at 10:44
  • You can check this post https://stackoverflow.com/a/42760546/10842900 – Indraraj26 Aug 08 '20 at 11:14
  • @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 Aug 08 '20 at 13:06
  • @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 (https://angular.io/guide/dynamic-component-loader) said nothing about that. – Alexander KLimov Aug 08 '20 at 13:26

1 Answers1

0

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();
  }
}
critrange
  • 5,652
  • 2
  • 16
  • 47
  • @Indraraj26, which solution? – critrange Aug 08 '20 at 10:58
  • This trigger an additional change detection when you wrap anything in setTimeout we need to find an real issue that causing an express change error – Indraraj26 Aug 08 '20 at 11:01
  • yeah so added another solution too for checking the detection manually – critrange Aug 08 '20 at 11:03
  • That will also call additional change detection. It is causing due to [formControl] in children – Indraraj26 Aug 08 '20 at 11:08
  • let factory = this.compFactoryResolver.resolveComponentFactory(MyFormComponent); let compRef = this.formSlotRef.createComponent(factory); compRef.changeDetectorRef.detectChanges() , This also resolve the error – Indraraj26 Aug 08 '20 at 11:11