Reputation: 857
as soon as I switch from module with component 1 to module with component 2 I got the following error:
ERROR Error: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'ngIf: [object Object]'. Current value: 'ngIf: [object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]'
Both modules use
ChangeDetectionStrategy.OnPush
When I subscribe my own, everything is fine:
this.bookings$.pipe(takeUntil(this._destroy$)).subscribe(res => console.log(res));
But as soon as I use async pipe for subscription, change detection breaks:
<ion-list *ngIf="bookings$ | async as bookings; else loading">
</ion-list>
The init of module/component 2 is faster then the destroy of component 1 when changing routes. So component 1 get the changes (filteredBookings) initiate by component 2 date change before detroy. But that shouldn't be a problem?
service:
constructor(
private afs: AngularFirestore
) {
this.bookingsCollection = afs.collection<Booking>('bookings');
this.bookingsCollection
.snapshotChanges()
.pipe(
takeUntil(this._destroy$),
map(actions => {
return actions.map(a => {
const data = a.payload.doc.data() as Booking;
const id = a.payload.doc.id;
return {id, ...data};
});
})
)
.subscribe((bookings: Booking[]) => {
this._bookings.next([...bookings]);
this.refreshFilteredBookings();
});
this.bookings$ = this._bookings
.asObservable()
.pipe(
filter(bookings => bookings !== null)
);
this.filteredBookings$ = this._filteredBookings
.asObservable()
.pipe(
filter(bookings => bookings !== null),
);
}
private refreshFilteredBookings(): void {
const bookings: Booking[] = JSON.parse(JSON.stringify(this._bookings.value));
const filteredBookings: Booking[] = bookings.filter(booking =>
moment(booking.date).isBetween(this.minDate, this.maxDate, null, '[]')
);
this._filteredBookings.next(filteredBookings);
}
setDate(date: Moment, type: string) {
this.minDate = date.startOf(type as unitOfTime.StartOf).format();
this.maxDate = date.endOf(type as unitOfTime.StartOf).format();
if (this._bookings.value) {
this.refreshFilteredBookings();
}
}
component 1:
ngOnInit() {
this.bookings$ = this._bookingService.filteredBookings$;
}
component 2:
ngOnInit() {
this.view = 'month';
this.date = moment().format();
this.onDateChange();
}
onDateChange() {
const m = moment(this.date);
this._bookingService.setDate(m, this.view);
}
Upvotes: 2
Views: 952
Reputation: 121
Are you using Angular 6?
The problem may be in lazy loading modules, It does not destroy the current component (component 1) while navigating to another component (component 2). so asycnPipe from Component 1 does not unsubscribe.
While component 2 is initializing, It changed the shared service's value, Component 1 is subscribing from shared service, and it's trying to re-render the view and caused this problem.
I think we can workaround by subscribing the observable from component and pass the value to view but this is not a good way.
You can check other way at here
Update: In my case, I change changeDetectionStrategy from Default to OnPush it solved my problem.
Upvotes: 2