Po pierwsze, zwróć uwagę, że ten wyjątek zostanie zgłoszony tylko wtedy, gdy uruchomisz aplikację w trybie deweloperskim (co ma miejsce domyślnie w wersji beta-0): Jeśli zadzwonisz enableProdMode()
podczas ładowania aplikacji, nie zostanie ona zgłoszona ( zobacz zaktualizowane plunk ).
Po drugie, nie rób tego, ponieważ ten wyjątek jest zgłaszany z ważnego powodu: krótko mówiąc, w trybie deweloperskim po każdej rundzie wykrywania zmian następuje natychmiast druga runda, która weryfikuje, czy żadne powiązania nie uległy zmianie od końca pierwszej, ponieważ oznaczałoby to, że zmiany są powodowane przez samo wykrywanie zmian.
W twojej grze, wiązanie {{message}}
jest zmieniane przez twoje wezwanie do setMessage()
, które dzieje się w ngAfterViewInit
haku, które występuje jako część początkowej tury wykrywania zmian. To samo w sobie nie jest jednak problematyczne - problem polega na tym, że setMessage()
zmienia to wiązanie, ale nie wyzwala nowej rundy wykrywania zmian, co oznacza, że ta zmiana nie zostanie wykryta, dopóki jakaś inna runda wykrywania zmian nie zostanie uruchomiona w innym miejscu.
Na wynos: Wszystko, co zmienia wiązanie, musi wywołać rundę wykrywania zmian, kiedy to nastąpi .
Zaktualizuj w odpowiedzi na wszystkie prośby o przykład, jak to zrobić : rozwiązanie @ Tycho działa, podobnie jak trzy metody w odpowiedzi @ MarkRajcok wskazał. Ale szczerze mówiąc, wszyscy czują się dla mnie brzydcy i źli, jak hacki, do których przyzwyczailiśmy się w ng1.
Aby mieć pewność, że są sporadyczne sytuacje, w których te hacki są odpowiednie, ale jeśli używasz ich na coś więcej niż tylko bardzo sporadycznie, to znak, że walczysz ramy zamiast całkowicie obejmując jego reaktywny charakter.
IMHO, bardziej idiomatyczny, „Angular2 sposób” podejścia do tego jest coś w stylu: ( 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
błędzie, wyjaśnia szczegółowo to zachowanie.