I'm having a problem with an Angular 6 application:
The problem
Let's say I have 2 components: parent and child.
the child has 2 inputs. While 1 input changes, inside the ngOnChanges() the child component emit somthing to the parent component.
Then the parent component changes the second input for the child component. I expect the change detection of the child component to get called once again- BUT IT'S NOT. The view of the child component shows old value of the second input.
Defenitions
the application has the following defenitions:
- All components use change detection strategy OnPush. that includes the root component.
- I'm using ngrx store. call markForCheck() or detectChanges() inside the reducer is not an option.
- The data goes down to the child component using async pipe, because it comes from the store using selector (observable).
- I can't cause the change of the second input earlier (at the parent component for example)- it has to happen after the child component recives a change of the first input.
To illustrate the case, I've created a simple demo project. There I don't use store, so I don't have any selectors.. instead I'm using rxjs Subject for the use of async pipe.
Here it is:
https://angular-ccejq4.stackblitz.io
Take a look the the console to understand what happens and when.
Bad solutions
What i've already tried:
- changing the change detection strategy at the root component to default. It works but this is not a good solution since it causing performance issues.
- call markForCheck() before and after the emit(!) - NOT WORKING.
- call detectchanges() before and after the emit(!) - NOT WORKING.
- subscribe to the selector at the parent component instead of using async pipe - NOT WORKING.
- call the emit from within a setTimeout - IT WORKS. but is there a better solution? a more Angular-driven one. because this solution feels more like a workaround.
- use ngAfterViewInit/ngAfterViewChecked and emit, call markForCheck() and detectChanges() from there - NOT WORKING.
I found that the new value arrives to the async pipe. the async pipe then calls markForCheck(). but it doesn't call detectChanges().. so a change detection cycle won't run. the view will change properly only at the next cycle of change detection- as you can see on my demo app.
Any ideas?
thanks!