Tout d'abord, notez que cette exception ne sera levée que lorsque vous exécutez votre application en mode dev (ce qui est le cas par défaut à partir de la beta-0): si vous appelez enableProdMode()
lors du démarrage de l'application, elle ne sera pas levée ( voir plunk mis à jour ).
Deuxièmement, ne faites pas cela car cette exception est levée pour une bonne raison: en bref, en mode dev, chaque cycle de détection de changement est suivi immédiatement par un deuxième cycle qui vérifie qu'aucune liaison n'a changé depuis la fin du premier, car cela indiquerait que les changements sont causés par la détection des changements elle-même.
Dans votre plunk, la liaison {{message}}
est modifiée par votre appel à setMessage()
, qui se produit dans le ngAfterViewInit
crochet, qui se produit dans le cadre du tour de détection de changement initial. Cela en soi n'est pas problématique cependant - le problème est que setMessage()
change la liaison mais ne déclenche pas une nouvelle ronde de détection de changement, ce qui signifie que cette modification ne sera détectée que lorsque une prochaine ronde de détection de changement sera déclenchée ailleurs.
Le point à retenir: tout ce qui modifie une liaison doit déclencher une ronde de détection des modifications lorsqu'il le fait.
Mise à jour en réponse à toutes les demandes d'un exemple de la façon de procéder : @ La solution de Tycho fonctionne, comme le font les trois méthodes de la réponse @MarkRajcok. Mais franchement, ils se sentent tous laids et mauvais pour moi, comme le genre de hacks sur lesquels nous nous sommes habitués en ng1.
Certes, il y a parfois des circonstances où ces hacks sont appropriées, mais si vous les utilisez sur quelque chose de plus qu'une très occasionnelle, il est un signe que vous vous battez le cadre plutôt que d' embrasser pleinement sa nature réactive.
À mon humble avis, une "façon angulaire2" plus idiomatique d'approcher cela est quelque chose comme: ( 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
erreur explique le comportement en détail.