Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

External promises don't trigger Angular2 change detection (UPDATE: they do)

Tags:

I'm working on an electron application, whose client side is written in Angular2.

I'm having the classic problem that a lot of people have encountered (eg. here and here), namely that I'm updating my component's data, but the view doesn't get updated because Angular doesn't know that the data has changed. The solutions people suggest (see above and also here) is to manually run change detection, either on the whole component tree, or part of it (similar to Angular 1's $rootScope.$digest and $scope.$digest).

However, I'd like to avoid wrapping all my data changes in zone.run() calls, as it slightly defeats the purpose of using Angular.

I'm pretty sure I know why this happens: I'm creating Bluebird Promises outside of Angular, in electron code (ie, the main process), and these aren't Zone aware, so they don't notify Angular of the changes.

I don't know how to solve it, though. What can I do to create Zone aware promises in my electron code, to avoid having to manually run change detection all the time? Can I convert my Bluebird Promises to Zone aware Promises somehow?

EDIT: I think I was wrong, Bluebird promises aren't Zone aware even if created within angular. They're just not Zone aware in general.

EDIT 2: I was completely wrong in the previous edit. Bluebird promises work just fine with zones. However, in the context of an electron application, creating a promise in the main electron process and using it in the renderer process (where Angular lives), doesn't work, as the returned promise isn't zone-aware. Creating the promise from Angular code worked.

like image 592
FrontierPsycho Avatar asked Aug 09 '16 15:08

FrontierPsycho


People also ask

What triggers Angular change detection?

Angular runs its change detection mechanism periodically so that changes to the data model are reflected in an application's view. Change detection can be triggered either manually or through an asynchronous event (for example, a user interaction or an XMLHttpRequest completion).

Does Async pipe triggering change detection?

Async pipe does't trigger changeDetection and do not redraw value in UI.

How do observable notify when a change is detected?

An observable notices a mutation in the object without creating a new reference for it. So, you can subscribe to an observable, and, whenever a change happens, manually run the change detector inside the subscribe method to update the view.

What is the default component change detection strategy in Angular?

Default change detection strategy is applied to the component while it is created. If a component strategy is not configured, it is marked as default. In this strategy, the change detection cycle runs on each and every event that occur inside the Component.


1 Answers

Promises don't make Angular run change detection with ChangeDetectionStrategy.OnPush except when you use the async pipe ... | async.

When code is initialized outside Angular2 it runs outside Angulars zone. What you can do is to move initialization inside your Angular2 code or use ´zone.run(...)to move execution inside Angulars zone. There is nothing bad aboutzone.run(...)`.

If the code executed only changes local properties of a component you can use ChangeDetectorRef.detectChanges() to run change detection for this component.

If the code causes changes in other components (like for example this.router.navigate(...), then detectChanges() is not sufficient. For this case zone.run() should be used.

setTimeout(...) triggers change detection for the whole application and should be avoided as a way to invoke change detection manually.

like image 99
Günter Zöchbauer Avatar answered Sep 22 '22 16:09

Günter Zöchbauer