简体   繁体   中英

Angular loading button ExpressionChangedAfterItHasBeenCheckedError

I have this component I use in my application and for the most part it works fine. It's ts file looks like this:

import { Component, Input, OnInit, OnChanges } from '@angular/core';
import { Router } from '@angular/router';

import { LoadingService } from '@pyb-services/loading.service';

@Component({
  selector: 'pyb-loading-button',
  templateUrl: './loading-button.component.html',
  styleUrls: ['./loading-button.component.scss']
})
export class LoadingButtonComponent implements OnInit, OnChanges {
  @Input() link: any[] = []
  @Input() target: string
  @Input() navigateAfter: boolean
  clicked: boolean = false
  loading: boolean = false; // Has to be false by default, because sometimes everything has loaded before this button has come on the page

  constructor(
    private router: Router,
    private loadingService: LoadingService
  ) {
  }

  ngOnInit() {
    this.loadingService.onLoadingChanged.subscribe(isLoading => this.loading = isLoading);
  }

  ngOnChanges() {
    this.navigateWhen();
  }

  click(): void {
    this.clicked = !this.clicked;
    this.navigateWhen();
  }

  private navigateWhen(): void {
    if ((!this.loading || this.navigateAfter) && this.clicked && this.link.length) {
      this.router.navigate(this.link); 

      this.clicked = false;
    }
  }
}

And the template file looks like this:

<button class="btn btn-xl btn-secondary" type="button" [disabled]="loading && !navigateAfter" (click)="click()" [scrollTo]="target"
  offset="10" [ngSwitch]="loading">
  <span class="spinner" *ngSwitchCase="true">
    <span class="bounce1"></span>
    <span class="bounce2"></span>
    <span class="bounce3"></span>
  </span>
  <span *ngSwitchDefault>Next step</span>
</button>

Like I have said, it seems to work fine. But, if another process kicks off an http request, then I get the error:

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

which is moaning about the loading property changing in the loading button component. Does anyone know how I can fix this?

Here is the issue with variable loading which is being changed while Change Detection has been trigger. To avoid this error set the value of loading in separate thread.

  ngOnInit() {
    this.loadingService.onLoadingChanged.subscribe(isLoading => 
       Promise.resolve(null).then(() => this.loading = isLoading)
    );
  }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM