0

I understand that the change detection will fire for OnPush marked component if the input property changes (there are others way too).

But I don't have an input property in my child component and I have a service injected into my component. I have subscribed the observable exposed by the service inside this child component. Now inside the subscribe callback method I change one of my child component's private property's value. The template of the component is bonded to this property.

So the problem is when the observer publishes an event my subscriber callback is called, and it changes the property value but the view doesn't reflect the changes. The UI only updates when I click somewhere in my page.

changeDetection: ChangeDetectionStrategy.OnPush

Update 1: Plunker added

6
  • Have you tried to use async pipe or cdRef.markForCheck()? And where is your code? Commented Apr 30, 2017 at 20:23
  • I can't use asynchronous pipe as my template is binded to a private property of component example a string. And CDR.markForCheck() I read but isn't it an overkill as it will go back till the anscetor root component by firing CD? I don't know how to post a plunker, will Google and add shortly. Thanks. Commented Apr 30, 2017 at 20:31
  • No, markForCheck doesn't go back to the ancestor root. That's ApplicationRef.tick(). markForCheck makes the component not being skipped on the next change detection turn. Commented Apr 30, 2017 at 20:32
  • Actually I went through this, here the last paragraph of the answer says it fires till root stackoverflow.com/questions/35386822/… Commented Apr 30, 2017 at 20:40
  • don't bind to private prop - it is not AOT compatible. Commented Apr 30, 2017 at 20:53

1 Answer 1

2

So, the comments are totally right. markForCheck() will cause it to go up to the root, but that's not a bad thing..

If your app goes: root > section > page > area > row > list and you make changes on your list then you would want to notify the parent items that changes have happened. Maybe you need to grow bigger now that more data is loaded, or trigger a scroll, or all sorts of stuff.

Remember though that you'll have to wait for a tick and if you're using onPush() on the parents as well without being notified that a child has changed with markForCheck() the detection will never reach your child, that's why it goes all the way.

The other method is manually triggering with detectChanges() This will run only on the local component and treats the node that called detectChanges() as the root..

Also, if you're displaying any property of your component it isn't technically Private. Javascript will allow it of course but test suites and I think even the compiler will complain. if you for whatever MUST do it, display it with a public getter.. like this:

Private _mySuperSecret: 'I am Batman';
Public get mySecret() { return this._mySuperSecret; };
Sign up to request clarification or add additional context in comments.

4 Comments

I have edited my question to add plunker. Also in the plucker when I use detectChanges() it works, but in my actual code which I can't share detectChanges() doesn't works. But markForChanges() works. I am using angular 2.4.0 version. Also I didn't understand the 3rd paragraph of your answer, can you please help me in understanding that. I am confused about the behaviors of my app now.
Yeah the sentence kinda sucks. What I meant is say you have a parent component(A) that is onPush() and a child (B) that is onPush() that again has a child (C) that is onPush() and this is where you trigger a change. The reason markForCheck() goes up the tree to root regardless is the detector starts at the root and says "A do you have changes?" if it doesn't, it skips it, and the changes on child C would never be detected. Therefore, they mark all the parents to be tested so the actually changed child will be detected and updated
If you meant about the private thing, private is reserved for internal data. It's generally frowned upon to expose it in any way, including the view layer of your component. Javascript of course doesn't care but Typescript can and the Angular Compiler does too. When you move to the current 4.X branch it would likely throw errors. Either switch it to public or create a public read-only function like my example
thanks for the explanation. markForChanges() works in my code but not detect changes(). Any reason that you can think of why. Because above pic code works for both but in my actual code only markForChanges () works.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.