Angular interpolated value display not updating wh

2019-04-16 01:47发布

问题:

Angular 6.0.1.

This problem is manifesting itself inside a large application, but I created a simple component to try and see what is going on. The simple component has a simple template:

{{myProp}}

In the ngOnInit, I set this.myProp = 'hello'; and I see the word hello on screen as I would expect. So far so good.

However, if I now try to update the value of myProp in a setTimeout, it never updates the UI:

this.myProp = 'hello';
setTimeout(() => {
  this.myProp = 'goodbye';
}, 3000);

The value shown in the UI is still hello.

If I inject ChangeDetectorRef in my constructor and call cdr.detectChanges() inside the timer, the UI updates.

Is this expected behavior, or what am I doing wrong? I wouldn't expect to have to call detectChanges for this. I have not changed the ChangeDetectorStrategy for the component so it is still default.

Note, that in the "real" app, I'm not updating myProp in a timer, but inside an Observable subscription. The UI is not updating there and that is what has led me to investigate this and end at the timer as the simplest possible reproduction of the problem. As near as I can tell, updating the property value in any type of async manner is not showing the change in the UI.

Update

I think that my reference to setTimeout confused things. I was using that as a means of debugging. Instead of trying to rework this question, I posted a new question here (Angular interpolated value not updating on subscription) with a better explanation and the ngRx code that is causing me grief. Thanks.

Update #2 The problem was caused by a parent component having its ChangeDetectionStrategy set to OnPush. See the question I referenced above.

Thanks,

TTE

回答1:

This is the expected action. The javascript method Window setTimeout is a Window command. This means that it is called outside the main zone.js thread (by which I mean the general change detection contained out of box in an Angular application), which is the expected plan. If you would like to contain your setTimeout() method you need to assign it to a variable contained inside your Angular TypeScript application.

This behavior is the most distinct when using a similar method in the same family of functions called from window: the Window setInterval() Method

You are able to contain this, and similar Window methods. The setTimeout() command needs the ChangeDetectorRef attached to it to detect changes in order to listen to Events Emitted. You can also insert commands by assigning the executed method to a component variable (similar to this answer on how to stop setInterval() after a component is destroyed here).