Innanzitutto, tieni presente che questa eccezione verrà generata solo quando esegui la tua app in modalità dev (che è il caso per impostazione predefinita a partire da beta-0): se chiami enableProdMode()
quando esegui il bootstrap dell'app, non verrà generata ( vedi plunk aggiornato ).
In secondo luogo, non farlo perché questa eccezione viene generata per una buona ragione: in breve, quando si è in modalità dev, ogni round di rilevamento delle modifiche è immediatamente seguito da un secondo round che verifica che nessun binding sia cambiato dalla fine del primo, poiché ciò indicherebbe che i cambiamenti sono causati dal rilevamento stesso del cambiamento.
Nel plunk, l'associazione {{message}}
viene modificata dalla chiamata a setMessage()
, che avviene in modalità ngAfterViewInit
hook, che si verifica come parte del turno di rilevamento delle modifiche iniziali. Ciò di per sé non è problematico, il problema è che setMessage()
cambia l'associazione ma non attiva un nuovo ciclo di rilevamento delle modifiche, il che significa che questo cambiamento non verrà rilevato fino a quando non verrà attivato da qualche altra parte il futuro ciclo di rilevamento delle modifiche.
Il takeaway: tutto ciò che cambia un'associazione deve attivare un round di rilevamento delle modifiche quando lo fa.
Aggiorna in risposta a tutte le richieste per un esempio di come farlo : la soluzione di @ Tycho funziona, come fanno i tre metodi nella risposta @MarkRajcok. Ma francamente, si sentono tutti brutti e sbagliati per me, come il tipo di hack a cui ci siamo abituati appoggiandoci in ng1.
A dire il vero, ci sono circostanze occasionali in cui questi hack sono appropriati, ma se li stai usando su qualcosa di più di una base molto occasionale, è un segno che stai combattendo il framework piuttosto che abbracciare completamente la sua natura reattiva.
IMHO, un modo più idiomatico di "Angular2" per avvicinarsi a questo è qualcosa sulla falsariga di: ( 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
sull'errore spiega il comportamento in modo dettagliato.