Please explain to me why I keep getting this error: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked.
Obviously,
@HostBinding
can be a confusing source of this error.For example, lets say you have the following host binding in a component
// image-carousel.component.ts
@HostBinding('style.background')
style_groupBG: string;
For simplicity, lets say this property is updated via the following input property:
@Input('carouselConfig')
public set carouselConfig(carouselConfig: string)
{
this.style_groupBG = carouselConfig.bgColor;
}
In the parent component you are programatically setting it in ngAfterViewInit
@ViewChild(ImageCarousel) carousel: ImageCarousel;
ngAfterViewInit()
{
this.carousel.carouselConfig = { bgColor: 'red' };
}
Here's what happens :
carousel
(via ViewChild)carousel
until ngAfterViewInit()
(it will be null)style_groupBG = 'red'
background: red
on the host ImageCarousel componentcarousel.style.background
and isn't clever enough to know that this isn't a problem so it throws the exception.One solution is to introduce another wrapper div insider ImageCarousel and set the background color on that, but then you don't get some of the benefits of using HostBinding
(such as allowing the parent to control the full bounds of the object).
The better solution, in the parent component is to add detectChanges() after setting the config.
ngAfterViewInit()
{
this.carousel.carouselConfig = { ... };
this.cdr.detectChanges();
}
This may look quite obvious set out like this, and very similar to other answers but there's a subtle difference.
Consider the case where you don't add @HostBinding
until later during development. Suddenly you get this error and it doesn't seem to make any sense.