Angular problem Error: ExpressionChangedAfterItHasBeenCheckedError. value null

142 Views Asked by At

i have this console error in my angular6 project : Error: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'flag: '. Current value: 'flag: null'.

this is the code in the ts component child

@Input() flag: any;

this is the code in the html component child


 <div *ngIf="flag !== 'ABBONAMENTO_MDA'">
   <div class="form-group col-lg-3 col-md-3">
     // something else
   </div>
 </div>
 <div *ngIf="flag === 'ABBONAMENTO_MDA'">
  <div class="form-group col-lg-3 col-md-3">
    // something else
  </div>    

this is the code in the component father

 <app-repertorio
       [flag]="eventoSelezionato" // here i intercept the state of flagMda
 </app-repertorio>

3

There are 3 best solutions below

0
On

Suppose you have a parent component A and a child component B. The A component has a name and text properties. In its template it uses the expression that references name property:

template: '<span>{{name}}</span>'

And it also has B component in its template and passes the text property to this component through input property binding:

@Component({
    selector: 'a-comp',
    template: `
        <span>{{name}}</span>
        <b-comp [text]="text"></b-comp>
    `
})
export class AComponent {
    name = 'I am A component';
    text = 'A message for the child component`;
    ...
}

So here is what happens when Angular runs change detection. It starts by checking A component. The first operation in the list is to update bindings so it evaluates text expression to A message for the child component and passes it down to the B component.It also stores this value on the view:

view.oldValues[0] = 'A message for the child component';

Then it calls the lifecycle hooks mentioned in the list.

Now, it performs the third operation and evaluates the expression {{name}}to the text I am A component. It updates the DOM with this value and puts the evaluated value to the oldValues:

view.oldValues[1] = 'I am A component'; Then Angular performs the next operation and runs the same check for the child B component. Once the B component is checked the current digest loop is finished.

If Angular is running in the development mode it then runs the second digest performing verification operations I listed above. Now imagine that somehow the property text was updated on the A component to the updated text after Angular passed the value A message for the child component to the B component and stored it. So it now runs the verification digest and the first operation is to check that the property text is not changed:

AComponentView.instance.text === view.oldValues[0]; // false 'A message for the child component' === 'updated text'; // false Yet it has and so Angular throws the error ExpressionChangedAfterItHasBeenCheckedError.

The same holds for the third operation. If the name property was updated after it was rendered in the DOM and stored we’ll get the same error:

AComponentView.instance.name === view.oldValues[1]; // false 'I am A component' === 'updated name'; // false

so the error can be resolved by forcing change detection by:

ngAfterViewInit() {
        this.cd.detectChanges();
    }

taken from the link: https://indepth.dev/everything-you-need-to-know-about-the-expressionchangedafterithasbeencheckederror-error/

1
On

Initializing the flag variable with some initial value should resolve this problem. And this also allows to have an initial state for your component to fallback to just in case the flag value is undefined through the input eventoSelezionato.

@Input() flag: string = 'INITIAL_VALUE';

0
On

just use the hook AfterViewChecked and the ChangeDetectorRef service of angular. The change Detector will help collects all views that are to be checked for changes.

constructor(private cdRef: ChangeDetectorRef) {}

ngAfterViewChecked() {
      this.cdRef.detectChanges();
  }