[angular2] Observable and ChangeDetectionStrategy.OnPush question

221 views
Skip to first unread message

Christophe HOARAU

unread,
Jun 21, 2016, 1:35:22 PM6/21/16
to AngularJS
Hi,

Could someone help me understand why my view is not updated in the following plunker when I'm using ChangeDetectionStrategy.OnPush.

According to my understanding when an Observable changes the view should be updated.

Could someone also explain me why this.dataSource is not initialized in my AppComponent constructor ?

Thanks a lot.

Zlatko Đurić

unread,
Jun 22, 2016, 4:51:03 AM6/22/16
to AngularJS
Hello,

I can try, as a method of learning myself about change detection :)


On Tuesday, June 21, 2016 at 7:35:22 PM UTC+2, Christophe HOARAU wrote:
Hi,

Could someone help me understand why my view is not updated in the following plunker when I'm using ChangeDetectionStrategy.OnPush.

You don't need the ChangeDetectionStrategy.OnPush on that subcomponent, that is your main issue. If you just comment out Line 7 in subComponent.ts, the example works as (presumably) intended.

But why?

Because OnPush strategy tells Angular component to only check for changes if the reference (on @Input) changes. But it didn't - your Input is always parent component's `data$` observer. Observer did not change.

Now, it also explains (at least partially, at least to me) why you never see "test 1" string. Both first and second changes (test 1 and test 2) were done in the callback to data$ observer constructor. And piled up there. And after all of those, observer already had the latest value "test 2". Then you do constructrors and OnInit calls. So by the time change comes in to your subcomponent, it only has one meaningful change - the first one it sees is from null to test 2.



According to my understanding when an Observable changes the view should be updated.

Observable didn't change. Only it's value. You always have a single reference to a single event emitter or in this case, observable. And OnPush strategy says to not perform deep checks.
If you comment out the OnPush strategy, then "Angular has to be conservative" and run change checks on your objects even if the reference to them did not change.

I found out most of this in this nice article.
 

Could someone also explain me why this.dataSource is not initialized in my AppComponent constructor ?

I believe it's because of this: you subscribe to this.data$ only in OnInit method. If you don't subscribe to observables, they don't run, from what I've learned so far.
As a test, I've added a this.data$.subscribe(); just above that console.log line - and really, then I got the dataSource to be logged.


 

Thanks a lot.


Thank you for a chance to learn something new :)
 

Zlatko Đurić

unread,
Jun 22, 2016, 4:54:04 AM6/22/16
to AngularJS
Minor correction - when I wrote "your Input is always parent component's `data$` observer. Observer did not change." I should have said Observable instead.


And an addition: "If you don't subscribe to observables, they don't run, from what I've learned so far." I've learned this when my http calls didn't work :)

Christophe HOARAU

unread,
Jun 22, 2016, 6:45:52 AM6/22/16
to AngularJS
Hi,

Thanks for your detailed responses. I found the problem for the sourceData, but I still don't understand the onPush issue. According to what I've read in several places, onPush is a good way to reduce 'watchers'/'change detections' by considering inputs as immutable. This match perfectly what you've said but on those same docs it was said that onPush is also meant to be used with observable. So there must be a way to make this work with observable no ?
Even the link you've provided talks about this, but does not explain how to implement it with observable.


Thanks.

Zlatko Đurić

unread,
Jun 22, 2016, 6:49:14 AM6/22/16
to ang...@googlegroups.com
Yeah, did you check the last section of that linked article?

TL;DR: since the observable ref does not change, you need to:
- inject change detector ref to your component
- call changeDetector.markChanged() in that subscription callback.

Look for more details closer to the end of the article.




--
You received this message because you are subscribed to a topic in the Google Groups "AngularJS" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/angular/M-Zbr14-j0o/unsubscribe.
To unsubscribe from this group and all its topics, send an email to angular+u...@googlegroups.com.
To post to this group, send email to ang...@googlegroups.com.
Visit this group at https://groups.google.com/group/angular.
For more options, visit https://groups.google.com/d/optout.



--
Zlatko

Christophe HOARAU

unread,
Jun 22, 2016, 6:52:18 AM6/22/16
to AngularJS
Yes I just noticed right after my post,

Sorry it's now working great !!!

Thanks a lot.
Reply all
Reply to author
Forward
0 new messages