I'm running into a problem making my UI update in a situation where I share data between a parent directive and child components. An @Input()
binding exists on the parent, and the data is then internally passed to the child components on ngOnChanges
using @ContentChildren()
. This way I don't have to bind my data to the parent and all child components every time I use the component.
To limit the amount of change detection cycles on the inner components, I am using the ChangeDetectionStrategy.OnPush
strategy. I then trigger my own change detection when the data is passed from the parent to the children.
This works great, except the change detection is now called before other data changes are processed deeper in the hierarchy. This leads to stale data that's always behind a cycle.
Here's a StackBlitz which roughly represents my current situation:
https://stackblitz.com/edit/angular-ivy-2tszsu
When updating the data, you'll see that with the OnPush strategy, the Template
value is always the previous Data
value.
PS. In this example data
and templateData
are one and the same for simplicity, but in my use case there are various unique properties.
From my understanding, here's what's happening:
@Input() data
onParentComponent
changes.ngOnChanges
onParentComponent
fires and passes new data toChildPushComponent
using my functionsetData(data)
.ChildPushComponent
fires change detection insidesetData(data)
. This later makes the UI update with new thedata
and oldtemplateData
.@Input() templateData
onTemplateDirective
changes.
These are ignored because theChildPushComponent
has already detected changes beforehand.
I'm looking for a solution to make the template value visually update at the same time as the other values (i.e. when I run the change detection manually inside ChildPushComponent
). Preferably without setTimeout trickery and without removing the OnPush strategy. Any help is much appreciated.