ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'undefined'

后端 未结 10 1587
Happy的楠姐
Happy的楠姐 2020-12-07 18:27

I know there are a lot of same questions already posted in stack-overflow and tried different solutions to avoid the run-time error but None of them are working for me.

相关标签:
10条回答
  • 2020-12-07 18:42

    *NgIf can create problem here , so either use display none css or easier way is to Use [hidden]="!condition"

    0 讨论(0)
  • 2020-12-07 18:43
    setTimeout(() => { // your code here }, 0);
    

    I wrapped my code in setTimeout and it worked

    0 讨论(0)
  • 2020-12-07 18:45

    Try this, to call your code in ngOnInit()

    someMethod() // emitted method call from output
    {
        // Your code 
    }
    
    ngOnInit(){
      someMethod(); // call here your error will be gone
    }
    
    0 讨论(0)
  • If you are using <ng-content> with *ngIf you are bound to fall into this loop.

    Only way out I found was to change *ngIf to display:none functionality

    0 讨论(0)
  • 2020-12-07 18:49

    The ngAfterContentChecked lifecycle hook is triggered when bindings updates for the child components/directives have been already been finished. But you're updating the property that is used as a binding input for the ngClass directive. That is the problem. When Angular runs validation stage it detects that there's a pending update to the properties and throws the error.

    To understand the error better, read these two articles:

    • Everything you need to know about the ExpressionChangedAfterItHasBeenCheckedError error
    • Everything you need to know about change detection in Angular

    Think about why you need to change the property in the ngAfterViewInit lifecycle hook. Any other lifecycle that is triggered before ngAfterViewInit/Checked will work, for example ngOnInit or ngDoCheck or ngAfterContentChecked.

    So to fix it move renderWidgetInsideWidgetContainer to the ngOnInit() lifecycle hook.

    0 讨论(0)
  • 2020-12-07 18:52

    I had the same issue trying to do something the same as you and I fixed it with something similar to Richie Fredicson's answer.

    When you run createComponent() it is created with undefined input variables. Then after that when you assign data to those input variables it changes things and causes that error in your child template (in my case it was because I was using the input in an ngIf, which changed once I assigned the input data).

    The only way I could find to avoid it in this specific case is to force change detection after you assign the data, however I didn't do it in ngAfterContentChecked().

    Your example code is a bit hard to follow but if my solution works for you it would be something like this (in the parent component):

    export class ParentComponent implements AfterViewInit {
      // I'm assuming you have a WidgetDirective.
      @ViewChild(WidgetDirective) widgetHost: WidgetDirective;
    
      constructor(
        private componentFactoryResolver: ComponentFactoryResolver,
        private changeDetector: ChangeDetectorRef
      ) {}
    
      ngAfterViewInit() {
        renderWidgetInsideWidgetContainer();
      }
    
      renderWidgetInsideWidgetContainer() {
        let component = this.storeFactory.getWidgetComponent(this.dataSource.ComponentName);
        let componentFactory = this.componentFactoryResolver.resolveComponentFactory(component);
        let viewContainerRef = this.widgetHost.viewContainerRef;
        viewContainerRef.clear();
        let componentRef = viewContainerRef.createComponent(componentFactory);
        debugger;
        // This <IDataBind> type you are using here needs to be changed to be the component
        // type you used for the call to resolveComponentFactory() above (if it isn't already).
        // It tells it that this component instance if of that type and then it knows
        // that WidgetDataContext and WidgetPosition are @Inputs for it.
        (<IDataBind>componentRef.instance).WidgetDataContext = this.dataSource.DataContext;
        (<IDataBind>componentRef.instance).WidgetPosition = this.dataSource.Position;
        this.changeDetector.detectChanges();
      }
    }
    

    Mine is almost the same as that except I'm using @ViewChildren instead of @ViewChild as I have multiple host elements.

    0 讨论(0)
提交回复
热议问题