I have two components, both of which are set to OnPush
. The parent component sets accountLoading
to true once getAccount()
is called, then sets accountLoading
to false once the call is completed. As expected, the console outputs:
this.accountLoading true
followed by:
this.accountLoading false
Yet the template doesn't update, and is stuck thinking that accountLoading
is true. How do I get the template to update as expected when the value changes? I'd like to keep the change detection as OnPush.
Parent component:
TypeScript:
public accountLoading: boolean;
...
getAccount() {
this.accountLoading = true;
this.authStore
.pipe(select(fromAuthStore.getAccountData))
.subscribe(account => {
if (account) {
this.accountLoading = false;
}
console.log('this.accountLoading', this.accountLoading);
});
// Loading account if it hasn't yet been loaded
this.authService.getAccount();
}
HTML:
<child-component
[accountLoading]="accountLoading">
</child-component>
Child component:
TypeScript:
@Input() accountLoading: boolean;
...
HTML:
<p *ngIf="accountLoading">
Loading...
</p>
Try a behavior subject
public accountLoading$: BehaviorSubject<boolean>(false);
...
getAccount() {
this.accountLoading$.next(true);
this.authStore
.pipe(select(fromAuthStore.getAccountData))
.subscribe(account => {
if (account) {
this.accountLoading$.next(false);
}
});
// Loading account if it hasn't yet been loaded
this.authService.getAccount();
}
and use the async pipe in the template
<p *ngIf="accountLoading$ | async">
Loading...
</p>
I have written a library to take care of a lot of this sort of state management for you, https://github.com/adriandavidbrand/ngx-rxcache. Have a read about it here https://medium.com/@adrianbrand/angular-state-management-with-rxcache-468a865fc3fb