最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Angular 7, Ngrx, ExpressionChangedAfterItHasBeenCheckedError - Stack Overflow

programmeradmin10浏览0评论

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 ponent 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

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 ponent 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

Share Improve this question asked Jun 19, 2019 at 8:41 qubitsqubits 1,3073 gold badges21 silver badges53 bronze badges 2
  • 1 I don't know what the rest of the logic of your ponent is but if it's just a presentational ponent you could set the changeDetection: ChangeDetectionStrategy.OnPush. This way the change detector will be called only when the input is updated – Antonis Commented Jun 19, 2019 at 9:20
  • Changing the push detection worked. Can you please formulate it into a nice answer? Thanks. – qubits Commented Jun 19, 2019 at 9:36
Add a ment  | 

2 Answers 2

Reset to default 10

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 ponent is a presentational ponent, 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-p',
  templateUrl: './app-your-p.ponent.html',
  styleUrls: ['./app-your-p.ponent.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush
})
<ng-container *ngIf="_navigationSelectedSafe$ | async as selectedSafe">
  <learning-navigation *ngIf="selectedSafe == _navigationLayout.location" 
    [(selectMode)]="_navigationModeSelected"></learning-navigation>
</ng-container>

This will prevent the learning-navigation element frop being displayed when the value of your observable is null, thus erasing your error.

EDIT

Use a timeout in your setter to resolve any further issue :

@Input()
set selectMode(mode: number) {
  setTimeout(() => this.mode = mode);
}
发布评论

评论列表(0)

  1. 暂无评论