t-ho / ngx-ui-loader

Multiple Loaders / spinners and Progress bar for Angular 5, 6, 7 and 8+
https://tdev.app/ngx-ui-loader/demo
MIT License
433 stars 41 forks source link

Angular Change Detection #90

Open denny99 opened 3 years ago

denny99 commented 3 years ago

Describe the bug The UI-Loader uses the new OnPush ChangeDetection Strategy and triggers update with cd.markForCheck(). This flags the Component to be checked on the next tick.

This tick however, might not come when everything uses the onPush Strategy.
Using cd.detectChanges() will guarantee the update.

This might cause too many updates, but right now it can get randomly stuck which blocks the whole ui with the foreground loader.

Expected behaviour The Component should always update the ui when it mutates its own data

denny99 commented 3 years ago

My hacky workaround with an onPush Wrapper Component:

    const stopLoader = this.loader.stopLoader.bind(this.loader);
    this.loader.stopLoader = (loaderId: string, taskId1?: string) => {
      stopLoader(loaderId, taskId1);
      cdr.detectChanges();
    };
sebastian-zarzycki-apzumi commented 3 years ago

I've noticed that if this component is present in the view, it tends to generate some weird side-effects that I cannot attribute to anything else. It would look like it prevents change detection in other components (i.e. marking for check in next tick that never comes), even if it's not triggered in any way (hide/show loader). Removing the component fixes the issue (view is updated as expected).

I'm not sure if this is related, as I currently struggle to understand how it could be relevant. Is markForCheck affecting also parent components that don't operate under OnPush strategy?

sebastian-zarzycki-apzumi commented 2 years ago

Did anybody get further into this? I'm losing my marbles here. I have a change in my application, that seems to be blocked by ngx-ui-loader (has to wait for another tick and change detection). As soon as I remove it, it is detected properly. I've tried numerous was to patch the component, changing to .detectChanges, run in zone, even switch to not use OnPush strategy altogether. Nothing helped. The only thing that helps is to force .detectChanges on my side of the code, when that change happens - but I don't like it and I don't think that loader should impact such things.

From what I could gather, it's not a code mentioned above - it never enters there, as loader is not ever initialized and shown by that time. But it must be something in its ngOnInit method. Apparently, it's the bindLoaderData part, but, again, I don't see anything fishy there.

sebastian-zarzycki-apzumi commented 2 years ago

Oh dear, disregard the above, I'm ashamed to admit that it had nothing to do with this loader and removing it "helped" the issue only because of sheer cascade of coincidences :)