I have a simple component which uses a service returning an Observable. Such Observable is used to control the creation of an html element via *ngIf
.
Here the code
@Component({
selector: 'hello',
template: `<h1 *ngIf="stuff$ | async as obj">Hello {{obj.name}}!</h1>`,
styles: [`h1 { font-family: Lato; }`],
})
export class HelloComponent implements AfterViewInit {
constructor(
private myService: MyService,
) {}
stuff$;
ngAfterViewInit() {
this.stuff$ = this.myService.getStuff();
}
}
@Injectable({
providedIn: 'root'
})
export class MyService {
getStuff() {
const stuff = {name: 'I am an object'};
return of(stuff).pipe(delay(100));
}
}
As you can see, getStuff()
returns and Observable with a delay
and everything works as expected.
Now I remove the delay
and I get the following error on the console
Error: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'ngIf: null'. Current value: 'ngIf: [object Object]'.
This is a Stackbliz that reproduces the case.
Is this inevitable? Is there a way to avoid this error?
This small example replicates a real world example, where MyService
queries a back end, so the delay.
This is for me relevant because I would like to be able to run tests in a synchronous way simulating the real backend and, when I try such an approach, I get the same result.