I can't figure out what I'm missing here.
SharedServiceA:
export class SharedServiceA {
somethingWasUpdated = new Subject();
updateSomething(value) {
this.somethingWasUpdated.next(value);
}
}
AnotherService:
export class AnotherService {
doSomething() {
this.sharedServiceA.updateSomething(true);
}
}
component-a.component.ts
export class ComponentA {
list = [];
isShowList = false;
ngOnInit() {
this.sharedServiceA.somethingWasUpdated
.pipe(takeUntil(this.destroyed))
.subscribe(
data => {
if (data) {
this.fetchData(); // Get data from another service, then populate list
}
}
);
}
fetchData() {
// Get data from another service
if (dataFound) {
this.list = dataFound;
this.isShowList = true;
} else {
this.isShowList = false;
}
}
}
component-a.component.html
<div *ngIf="!isShowList"> <!-- This is where ExpressionChangedAfterItHasBeenCheckedError points to: Previous value: 'ngIf: true'. Current value: 'ngIf: false' -->
List empty
</div>
<div *ngIf="isShowList">
Print something here
</div>
component-b.component.html
export class ComponentB {
ngOnInit() {
this.sharedServiceA.somethingWasUpdated
.pipe(takeUntil(this.destroyed))
.subscribe(
data => {
if (data) {
// Get data from another service
}
}
);
this.anotherService.doSomething(); // If I place this inside a setTimeout, I don't get the ExpressionChangedAfterItHasBeenCheckedError
}
}
This is the scenario:
Click on a button > ComponentA
gets created inside a tab
Click on another button > ComponentB
gets created inside another tab (basically side by side with ComponentA
) > ComponentA.fetchData()
> ExpressionChangedAfterItHasBeenCheckedError
Why would I get an ExpressionChangedAfterItHasBeenCheckedError
in ComponentA
after list
was populated and isShowList
was set to true
and why don't I get the error if I place this.anotherService.doSomething();
inside a setTimeout
?
How is this code violating the unidirectional data flow? Even after reading several articles, I'm still confused in this particular case.
Quick point, ExpressionChangedAfterItHasBeenChecked errors only visible in dev mode. Do not show in production mode.
In your component use changeDectectorRef like below:
import { ChangeDetectorRef} from "@angular/core";
constructor(private ref: ChangeDetectorRef){}
fetchData() {
// Get data from another service
if (dataFound) {
this.list = dataFound;
this.isShowList = true;
} else {
this.isShowList = false;
}
this.ref.detectChanges();
}
2nd method
If above doesnt work for you then use it in AfterViewChecked
life cycle hooks.
ngAfterViewChecked() {
this.ref.detectChanges();
}
Hope this helps you!!
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.