Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ExpressionChangedAfterItHasBeenCheckedError when you combine onLazyLoad and loading tags #8465

Closed
Michael-Ziluck opened this issue Jan 20, 2020 · 4 comments

Comments

@Michael-Ziluck
Copy link

I'm submitting a ... (check one with "x")

[x] bug report => Search github for a similar issue or PR before submitting
[ ] feature request => Please check if request is not on the roadmap already https://github.com/primefaces/primeng/wiki/Roadmap
[ ] support request => Please do not submit support request here, instead see http://forum.primefaces.org/viewforum.php?f=35

Plunkr Case (Bug Reports)

https://stackblitz.com/edit/github-ap6ryb

Current behavior
When you set loading = true within the onLazyLoad callback, Angular throws an ExpressionChangedAfterItHasBeenCheckedError.

Expected behavior
No such error should be thrown.

Minimal reproduction of the problem with instructions
See the stackblitz link above.

What is the motivation / use case for changing the behavior?
Being able to display the loading spinner while the content is loading should be a pretty standard feature.

Temporary Workaround:
Wrap everything within the callback method in a setTimeout block. Here is a forked version of the stackblitz I linked above that has this change: https://stackblitz.com/edit/github-ap6ryb-khx7a2

Please tell us about your environment:
Every environment encounters this error.

  • Angular version: All versions.

  • PrimeNG version: All versions

  • Browser: All

  • Language: All

This issue is similar to #3293 and #3041 but they are NOT the same. I did my research to make sure there are no existing issues and if there are solutions online.

I am aware of the fact that you can either use ChangeDetectorRef or simply wrap it in a setTimeout block. However, I feel like this should be supported natively. It seems odd that you can't combine them without using other workarounds.

@Michael-Ziluck Michael-Ziluck changed the title ExpressionChangedAfterItHasBeenCheckedError when you combine onLazyLoad and loading ExpressionChangedAfterItHasBeenCheckedError when you combine onLazyLoad and loading tags Jan 20, 2020
@cagataycivici cagataycivici added Type: Bug Issue contains a bug related to a specific component. Something about the component is not working Status: Pending Review Issue or pull request is being reviewed by Core Team labels Apr 3, 2020
@cagataycivici cagataycivici added this to the 9.0.6 milestone Apr 3, 2020
@cagataycivici cagataycivici removed Type: Bug Issue contains a bug related to a specific component. Something about the component is not working Status: Pending Review Issue or pull request is being reviewed by Core Team labels Apr 22, 2020
@cagataycivici cagataycivici removed this from the 9.0.6 milestone Apr 22, 2020
@cagataycivici
Copy link
Member

cagataycivici commented Apr 22, 2020

Should be fixed on your side I think;

lazyLoadCallback(event) {
        Promise.resolve(null).then(() => this.loading = true);

@cagataycivici cagataycivici removed their assignment Apr 22, 2020
@Michael-Ziluck
Copy link
Author

@cagataycivici So your recommended solution is to update the value outside of Angular's change detection scope rather than fix the lifecycle hooks?...

@adamturski
Copy link

@Michael-Ziluck I had the same issue and in my case initialize loading variable with true in variable definition solved the issue, I know that this should work either way but at least it is a good workaround, no need for setTimeout.
loading: boolean = true;

@majkers
Copy link

majkers commented Jan 17, 2022

@cagataycivici So your recommended solution is to update the value outside of Angular's change detection scope rather than fix the lifecycle hooks?...

This is really sick!. I have a http interceptor to fire loading indicator for all http request. More or less it looks like this:

intercept(httpRequest: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    if (httpRequest.url.indexOf('/assets') == -1) {
      return this.loadingService.showLoaderUntilCompleted(next.handle(httpRequest));
    }
    return next.handle(httpRequest);
  }

and

 showLoaderUntilCompleted<T>(obs$: Observable<T>): Observable<T> {
    return of(null)
      .pipe(
        tap(() => this.loadingOn()),
        concatMap(() => obs$),
        finalize(() => this.loadingOff())
      );
  }

and me too I get the same error because of wrong lifecycle hooks. And I had to use setTimeout to make it work. @cagataycivici keep in mind that people may want to use their solutions with loading indicator so it sholud work as expected!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants