问题
- Angular 6.0.1
- ngRx 6.0.1
I have an interpolated value set up in my View:
{{firstName}}
It is not updating when the value of the field it is bound to changes. The value is changing though - if I log it out to the console inside the subscription, I see the updated value. It just doesn't update in the UI.
Here's the relevant code:
Subscription from my component:
private subscribeToCurrentPerson(): void {
this.tState$ = this.store
.pipe(select(selectors.getCurrentPerson), takeWhile(() => this.componentActive))
.subscribe((cp: Person) => {
if (cp) {
const name: string = cp.primaryName.value.parsedValue.givenNames[0];
this.firstName = name;
console.log('name: ' + name); // <-- this shows correct new value
}
});
}
subscribeToCurrentPerson
is called from the component's ngOnInit. Prior to this, the firstName
property is undefined.
The selectors.getCurrentPerson
selector looks like this:
export const getCurrentPerson: MemoizedSelector<{}, Person> =
createSelector(getTState, (tState: ITState) => {
console.log('selector: ', tState); // <-- this logs the correct new value
return tState ? tState.currentPerson : null;
});
The currentPerson
value returned from the selector is a newly created object. This is happening on the first run of the application, so prior to this tState
is undefined.
If I inject ChangeDetectorRef
in my constructor and call cdr.detectChanges()
inside the subscription, the UI updates. But it seems to me I don't typically need to use ChangeDetectorRef
like this, that it should "just work".
I think the problem is my deeply nested property (cp.primaryName.value.parsedValue.givenNames
). I inherited these entities from a non-ngRx project, but I think my next step is to try flattening that structure to see if that makes ngRx and the Angular change detector happier.
Is there something else I'm missing?
Thanks,
TTE
UPDATE
I've take the deeply nested property out of the picture by simply updating a local property on my component inside the subscription. So the subscribeToCurrentPerson
function now looks like this:
private subscribeToCurrentPerson(): void {
this.tState$ = this.store
.pipe(select(selectors.getCurrentPerson), takeWhile(() => this.componentActive))
.subscribe((cp: Person) => {
this.myProp = 'goodbye';
this['newProp'] = 'world';
});
}
myProp
is an existing property on my component I added for testing.
newProp
does not exist until it is added via the bracket notation inside the subscription. Here's the results:
myProp
is not updated - it shows the value I assigned it when it was declared. However, if I do not assign a value when the property is declared, then the value assigned in the subscription is shown in the UI properly.newProp
is shown in the UI correctly
I am now completely baffled. It seems like once a property has a value it is never updated in the UI, even if the value itself does change (which I can tell by logging to the console after updating the value).
I'm not explicitly setting the ChangeDetectionStrategy
for the component, so it is Default
.
Everything works if I call detectChanges
, but I don't think that should be necessary.
回答1:
When a parent component has its change detection strategy set to OnPush
then this parent's tree of components will not be checked by angular's change detection mechanism, although this parent and its children's ngOnChanges
method is still being called every time any @Input
properties change. To let angular know that some component in this tree needs to update, inject a ChangeDetectorRef
into that component and use its API to notify angular about the update, e.g detectChanges
or markForCheck
回答2:
A lot of times data updates from component will not reflect the HTML template. In such a case, you can use interpolation with ternary operators.
{{firstName ? firstName : ''}}
It works for me. Hope this will work
来源:https://stackoverflow.com/questions/51690866/angular-interpolated-value-not-updating-on-subscription