まず、この例外は、アプリを開発モードで実行している場合にのみスローされることに注意してください(ベータ-0以降のデフォルトです):enableProdMode()
アプリをブートストラップするときに呼び出しても、スローされません(を参照)更新されたプランク)。
第二に、それをしないでくださいこの例外は正当な理由でスローされため、これを、開発モードでは、変更検出のすべてのラウンドの直後に、最初のラウンドの終了以降にバインディングが変更されていないことを確認する2番目のラウンドが続きます。これは、変更が変更検出自体によって引き起こされていることを示します。
プランクでは、最初の変更検出ターンの一部として発生するフックで発生{{message}}
するへの呼び出しによってバインディングが変更されます。それ自体は問題ありませんが、問題はsetMessage()
ngAfterViewInit
setMessage()
バインディング変更しますが、新しいラウンドの変更検出をトリガーしないことです。つまり、今後のラウンドの変更検出がどこかでトリガーされるまで、この変更は検出されません。
要点:バインディングを変更するものはすべて、変更時に一連の変更検出をトリガーする必要があります。
これを行う方法の例についてのすべての要求に応じて更新します。@ MarkRajcokが指摘した回答の 3つのメソッドと同様に、@ Tychoのソリューションが機能します。しかし率直に言って、ng1に頼っていたハックのように、それらはすべて私にとって醜く間違っていると感じています。
確かに、これらのハッキングが適切である状況は時々ありますが、ごくまれにしか使用していない場合は、フレームワークとの反応性を完全に受け入れるのではなく、フレームワークと戦っていることを示しています。
IMHO、これにアプローチするより慣用的な「Angular2の方法」は、次のようなものです。(plunk)
@Component({
selector: 'my-app',
template: `<div>I'm {{message | async}} </div>`
})
export class App {
message:Subject<string> = new BehaviorSubject('loading :(');
ngAfterViewInit() {
this.message.next('all done loading :)')
}
}
ExpressionChangedAfterItHasBeenCheckedError
の記事で、動作が詳細に説明されています。