1

I'm getting an error in my loading indicator and I don't understand why:

LoadingIndicatorComponent.html:2 ERROR Error: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'hidden: true'. Current value: 'hidden: false'.

I've got a simple loading indicator image:

<img class="loader" [hidden]="!isLoading" src="loading.svg" alt="Loading..." />

With the following code:

export class LoadingIndicatorComponent implements OnInit {
  public isLoading = false;
  constructor(private loader: LoadingIndicatorService) {
  }

  ngOnInit() {
    this.loader.IsLoading.subscribe((value) => {
      this.isLoading = value;
    });
  }
}

Which makes use of the following service:

export class LoadingIndicatorService {
  constructor() { }

  private workload = 0;
  private _loading: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
  public readonly IsLoading: Observable<boolean> = this._loading.asObservable();

  public StartWork(): void {
    this.workload++;
    this._loading.next(this.workload > 0);
  }

  public EndWork(): void {
    this.workload--;
    this._loading.next(this.workload > 0);
  }
}
Ralf de Kleine
  • 11,464
  • 5
  • 45
  • 87
  • Here is an very good exploration about this problem in angular. https://stackoverflow.com/questions/44691745/angular-4-expressionchangedafterithasbeencheckederror/44691880#44691880 – Gregor Doroschenko Apr 19 '18 at 07:17

2 Answers2

1

You are modifying value of isLoading during change detection cycle that is causing issue. which is this line of code

this.loader.IsLoading.subscribe((value) => {
  this.isLoading = value;
});

is loading modified by you service. so you need to put work around for this

this.loader.IsLoading.subscribe((value) => {
 Promise.resolve(null).then(() =>  this.isLoading = value);
});

answer is based on this post : Everything you need to know about the ExpressionChangedAfterItHasBeenCheckedError error

Pranay Rana
  • 175,020
  • 35
  • 237
  • 263
  • I've come across the article you've mentioned and didn't quite get the gist of it. Will take some more time to understand it better. Your solution does the trick though:) – Ralf de Kleine Apr 19 '18 at 07:27
0

I also faced this type problem. Use this

this.loader.IsLoading.subscribe((value) => {
    setTimeout(() => this.isLoading = value, 0)
});
  • 1
    It's only a workaround and not good solution. Read this article (https://blog.angularindepth.com/everything-you-need-to-know-about-the-expressionchangedafterithasbeencheckederror-error-e3fd9ce7dbb4) to understand how angular's change detection works. – Gregor Doroschenko Apr 19 '18 at 07:18
  • I think this is the right solution because here you're writing the least amount of code and getting the result you want. what's the definition of the right solution according to you? @GregorDoroschenko – MD KAMRUL HASAN SHAHED Apr 19 '18 at 07:27
  • 1
    Right solution would If you have explained the cause of this problem and right way how to resolve this problem. Your current answer resolves the problem, but this is a dirty workaround, which can cause more errors in the future. – Gregor Doroschenko Apr 19 '18 at 07:39