Why is the component in this simple plunk
@Component({ selector: 'my-app', template: `<div>I'm {{message}} </div>`, }) export class App { message:string = 'loading :('; ngAfterViewInit() { this.updateMessage(); } updateMessage(){ this.message = 'all done loading :)' } }
throwing:
EXCEPTION: Expression 'I'm {{message}} in App@0:5' has changed after it was checked. Previous value: 'I'm loading :( '. Current value: 'I'm all done loading :) ' in [I'm {{message}} in App@0:5]
when all I'm doing is updating a simple binding when my view is initiated?
Navigate up the call stack until you find a template expression where the value displayed in the error has changed. Ensure that there are no changes to the bindings in the template after change detection is run. This often means refactoring to use the correct component lifecycle hook for your use case.
Has it been created in a change detection hook? You've created component dynamically ("outside" of angular lifecycle), this means you need to control change detection manually. Yep!
As stated by drewmoore, the proper solution in this case is to manually trigger change detection for the current component. This is done using the detectChanges()
method of the ChangeDetectorRef
object (imported from angular2/core
), or its markForCheck()
method, which also makes any parent components update. Relevant example:
import { Component, ChangeDetectorRef, AfterViewInit } from 'angular2/core' @Component({ selector: 'my-app', template: `<div>I'm {{message}} </div>`, }) export class App implements AfterViewInit { message: string = 'loading :('; constructor(private cdr: ChangeDetectorRef) {} ngAfterViewInit() { this.message = 'all done loading :)' this.cdr.detectChanges(); } }
Here are also Plunkers demonstrating the ngOnInit, setTimeout, and enableProdMode approaches just in case.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With