was looking for a longer while but couldn't find anything.
I have a template like so:
<learning-navigation *ngIf="(_navigationSelectedSafe$ | async) == _navigationLayout.location" [(selectMode)]="_navigationModeSelected"></learning-navigation>
Where:
private _navigationSelected$: Observable<string>;
private _navigationSelectedSafe$ = new EventEmitter<any>(true);
...
this._navigationSelected$.subscribe(res => {
...
this._navigationSelectedSafe$.emit(res)
});
with the input of learning-navigation being a setter:
@Input()
set selectMode(mode: number) {
this.mode = mode;
}
This causes the error:
ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'selectMode: null'. Current value: 'selectMode: 1'.
I already tried changing the EventEmitter to a BehaviourSubject, forcing detectChanges() after ngInit and ngAfterChecked (Although this wouldn't be optimal even if it worked) and also wrapping it around in a container trying to pass the mode directly async into the component while just controlling the display with an extra if.
The current solution works and it doesn't seem there are any side effects but it throws the error regardless every time mode changes. Thanks
Your problem indicates that there was a change of value outside Angular's change detection. This can happen for multiple reasons. In your case it's the asynchronous nature of your input I guess.
If your component is a presentational component, you can set the change detection strategy to onPush
.
This way your change detector will run only when there's a new value on your input
example:
@Component({
selector: 'app-your-comp',
templateUrl: './app-your-comp.component.html',
styleUrls: ['./app-your-comp.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush
})