angulartypescriptngonchanges

How to fix Angular Error: NG0100 before ngOnChange is called


There are 2 child-components (bar/edit) under app-component, edit component will emit an @output number from ngOnChanges function to the app component . Which the app component will stored it like below.

app.component.ts

editCount:number=0;
editCountReceiver(data:number){
  this.editCount=data;
  console.log("app component receieved = "+this.editCount);
} 

app.component.html

<app-edit (send_edit_count)="editCountReceiver($event)"></app-edit>

The bar component will then get the number from the app component by using @input like below .

app.component.html

<app-search-bar [total_edit]="editCount"">

bar.component.typescript

@Input() total_edit: number  ; 

And then the error appeared.
"ERROR Error: NG0100: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: '0'. Current value: '1'.. "

One line of code is included in the error message, as shown below.

<app-search-bar [total_edit]="editCount"">

I was trying to fix this issue for couple of hours already and I have found out it has to do with the hook thing. So I decided to console.log almost all hooks for further investigation. The result is quite long so I just capture few lines that I think might be helpful.

enter image description here

Supposedly, since the value is bind with @input. I expect the ngOnChanges is called right after app component receive number and update bar component @input number accordingly.

But no, an error message is appeared before the ngOnChanges called. I presume it's because the @input data is updated slower than the afterViewChecked hook. So please, how can I fix this issue and make sure @input update is detected and applies before the afterViewChecked hook ?


Solution

  • As you describe, if you need to be notified, it's probably with a Subject that you must subscribe. Since I don't have all the code in your question, it's hard to give you a good answer.

    In that case, one component can emit the value with the Subject by calling next and the component that need to be notified can Subcribe to the same Subject.

    After some research, you can use a setter on the Input, but in this case, you will run after some problems if the value is passed by reference. (ex. An array, or an object).

    In that case, something like this can work:

    private editCountField: number;
    get countField(): number{
        return this.editCountField;
    }
    @Input() set countField(newCountField: number) {
        this.editCountField = newCountField;
        this.doSomething();
    }