0
votes

I am using ngScrollReveal, which causes a re-render every scroll event. I am calling a function through the HTML like follows:

<component [alternate]="toggleAlternate()">

The definition of toggleAlternate() looks like:

toggleAlternate() {
  this.alternate = !this.alternate;
  return this.alternate;
}

However, I get the following error on every scroll event:

ERROR Error: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'alternate: false'. Current value: 'alternate: true'.

I have tried a couple of solutions such as injecting ChangeDetectorRef and calling detectChanges() in the toggleAlternate() method, however, that did not fix the error. I am new to Angular and am not sure what I can do to fix this.

Is there a way to not call the toggleAlternate() method on every render?

Currently, the UI is working fine, but I would like to remove the console errors.

Update

I am trying to make my work experience as a timeline in which every entry is alternate to the previous one.

the following is where toggleAlternate() is called:

<app-work-ex-position *ngFor="let job of year[Object.keys(year)[0]].jobs" [job]=job [alternate]="toggleAlternate()">
</app-work-ex-position>

this is how the <app-work-ex-position /> component looks like:

<app-work-ex-timeline-entry (expand)="onExpandEntry($event)" class="{{alternate ? 'alternate' : ''}}">

<app-work-ex-timeline-entry-dot class="{{isExpanded ? 'primary-circle' : 'primary-circle circle-not-expanded'}}"
                      [size]="30"
                      [isAlternate]="alternate">
</app-work-ex-timeline-entry-dot>
</app-work-ex-timeline-entry>

Based on what the value of alternate is returned from the parent component i set the css class.

1
[alternate] is interpreted on every render and therefore toggleAlternate is called every render. Could you show the component that contains the alternate property? - David Walschots
@ChaitanyaKhanna have try this this.cd.detectChanges(); - Abhishek
@DavidWalschots I updated code above. let me know if something is still not clear. - Chaitanya Khanna
@Abhishek Can show me an example of how to use it. I did try this but maybe i m not using it properly. - Chaitanya Khanna
@ChaitanyaKhanna have you look at this (stackoverflow.com/questions/43375532/…). or use this one in AppComponent constructor(private cd: ChangeDetectorRef) { } ngAfterViewInit() { this.cd.detectChanges();} - Abhishek

1 Answers

0
votes

You should never call a function that changes component state from the HTML. This function will be called every change detection cycle and thus the component's state can never stabilise.

It seems that you want to set a CSS class within the component for every other instance. For this purpose you should use the even and odd variables exposed by *ngFor as can be found in the documentation.

Your code would need to be adapted as follows:

<app-work-ex-position 
    *ngFor="let job of year[Object.keys(year)[0]].jobs; even as isEven" 
    [isAlternate]="isEven">
</app-work-ex-position>
set isAlternate(value: boolean) {
  this.alternate = value;
}