Beachten Sie zunächst, dass diese Ausnahme nur ausgelöst wird, wenn Sie Ihre App im Entwicklungsmodus ausführen (was ab Beta-0 standardmäßig der Fall ist): Wenn Sie enableProdMode()
beim Booten der App aufrufen , wird sie nicht ausgelöst ( siehe) aktualisiert plunk ).
Zweitens, tu das nicht da diese Ausnahme aus gutem Grund ausgelöst wird: Kurz gesagt, im Dev-Modus folgt auf jede Änderungserkennungsrunde sofort eine zweite Runde, in der überprüft wird, ob sich seit dem Ende der ersten keine Bindungen geändert haben. Dies würde darauf hinweisen, dass Änderungen durch die Änderungserkennung selbst verursacht werden.
In Ihrem Plunk wird die Bindung {{message}}
durch Ihren Aufruf an geändert setMessage()
, was im ngAfterViewInit
Hook geschieht , der als Teil der anfänglichen Änderungserkennungsrunde auftritt. Das an sich ist jedoch nicht problematisch - das Problem ist dassetMessage()
die Bindung geändert aber keine neue Runde der Änderungserkennung ausgelöst wird. Dies bedeutet, dass diese Änderung erst erkannt wird, wenn eine zukünftige Änderungsrunde an einer anderen Stelle ausgelöst wird.
Das Mitnehmen: Alles, was eine Bindung ändert, muss eine Runde der Änderungserkennung auslösen, wenn dies der Fall ist.
Aktualisieren Sie als Antwort auf alle Anfragen nach einem Beispiel dafür : Die Lösung von @ Tycho funktioniert ebenso wie die drei Methoden in der Antwort, auf die @MarkRajcok hingewiesen hat. Aber ehrlich gesagt fühlen sich alle hässlich und falsch für mich an, wie die Art von Hacks, an die wir uns in ng1 gewöhnt haben.
Zwar gibt es gelegentliche Umstände, unter denen diese Hacks angemessen sind, aber wenn Sie sie nur gelegentlich verwenden, ist dies ein Zeichen dafür, dass Sie gegen das Framework kämpfen, anstatt dessen reaktive Natur voll zu nutzen.
IMHO, eine idiomatischere "Angular2-Methode", um dies zu erreichen, ist etwas in der Art von: ( 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
Fehler wissen müssen, erklärt das Verhalten ausführlich.