Пожалуйста, объясните мне, почему я постоянно получаю эту ошибку: ExpressionChangedAfterItHasBeenCheckederror: выражение изменилось после того, как он был проверен.
Очевидно, я только сделать это в dev режиме, он не'т случится на моем производстве построить, но это's очень раздражает и я просто не'т понять преимущества наличия ошибки в моей среде разработки, которая выиграла'т показать на прод ... наверное из-за моего непонимания.
Как правило, исправить это достаточно легко, я просто обернуть ошибку вызывает код в setTimeout такой:
в
setTimeout(()=> {
this.isLoading = true;
}, 0);
Или силу обнаружить изменения с конструктором, так: конструктор(частная диска: ChangeDetectorRef) {}`:
this.isLoading = true;
this.cd.detectChanges();
Но почему я постоянно натыкался на эту ошибку? Я хочу понять его, поэтому я могу избежать этих Сокс исправления в будущем.
У меня была аналогичная проблема. Глядя на крючки жизненного цикла документации, я изменил ngAfterViewInit
в ngAfterContentInit
и это сработало.
Эта ошибка указывает на реальные проблемы в вашем приложении, поэтому есть смысл бросить исключение.
В версии devmode` обнаружение изменений добавляет дополнительный поворот после каждого регулярного обнаружения изменений запустить, чтобы проверить, если модель изменилась.
Если модель изменилась между регулярным и дополнительная смена обнаружения свою очередь, это означает, что либо
оба плохие, потому что не понятно, как действовать, потому что модель никогда не может стабилизироваться.
Если угловые выполняется обнаружение изменения до тех пор, пока модель не стабилизируется, он может работать вечно. Если угловой не'т запустить обнаружение изменений, то мнение может не отражать текущее состояние модели.
Большое понимание, как только приехал, я понял угловые крючки жизненного цикла и их связи с обнаружением изменения.
Я пытался сделать угловой, чтобы обновить мировой привязан флаг *ngIf
элемента, и я пытался изменить этот флаг внутри ngOnInit()
жизнь крюк цикл другого компонента.
Согласно документации, этот метод вызывается после углового уже обнаружены изменения:
вызывается один раз, после первого ngOnChanges().
Поэтому обновление флаг внутри ngOnChanges()
выиграл'т начать обнаружения изменений. Затем, после обнаружения изменений, естественно, снова срабатывает, флаг'ы значение изменилось и ошибка.
В моем случае, я изменил это:
constructor(private globalEventsService: GlobalEventsService) {
}
ngOnInit() {
this.globalEventsService.showCheckoutHeader = true;
}
К этому:
constructor(private globalEventsService: GlobalEventsService) {
this.globalEventsService.showCheckoutHeader = true;
}
ngOnInit() {
}
и он исправил проблему :)
Обновление
Я настоятельно рекомендую начать с [ОП'Ответ С "я"] (https://stackoverflow.com/a/48216423/777285) во-первых: правильно думать о том, что может быть сделано в конструктор
против того, что должно быть сделано в ngOnChanges()`.
Оригинальной
Это скорее заметка, чем ответов, но это может помочь кому-то. Я наткнулся на эту проблему при попытке сделать наличие кнопки зависит от состояния форма:
<button *ngIf="form.pristine">Yo</button>
Насколько я знаю, этот синтаксис приводит к кнопку быть добавлен и удален из DOM в зависимости от состояния. Что в свою очередь приводит к ExpressionChangedAfterItHasBeenCheckederror`.
Исправление в моем случае (хотя я не'т утверждают, чтобы понять все последствия разницу), чтобы использовать дисплей: нет вместо этого:
<button [style.display]="form.pristine ? 'inline' : 'none'">Yo</button>
Там были интересные ответы, но я не'т показаться, чтобы найти один, чтобы соответствовать моим потребностям, ближайший из которых находится от @chittrang-Мишра, который относится только к одной конкретной функции, а не несколько тумблеров, как в мое приложение.
Я не хочу использовать [скрыто]
воспользоваться *ngIf
даже не будучи частью DOM, так что я нашел следующее решение, которое не может быть лучшим для всех, так как он подавляет ошибки, а не исправлять его, но в моем случае, когда я знаю конечный результат-это правильно, это вроде нормально для моего приложения.
То, что я сделал внедрению AfterViewChecked, добавить
конструктор(частная changeDetector : ChangeDetectorRef ) {}`, а затем
ngAfterViewChecked(){
this.changeDetector.detectChanges();
}
Я надеюсь, что это помогает другим, как и многие другие помогли мне.
В моем случае, я имел эту проблему на моем Spec-файл, при тестировании.
Я должен был изменить ngIf
к [скрыто]
в
<app-loading *ngIf="isLoading"></app-loading>
к
<app-loading [hidden]="!isLoading"></app-loading>
Выполните следующие действия:
import{ ChangeDetectorRef } from '@angular/core';
constructor( private cdRef : ChangeDetectorRef ) {}
functionName() {
yourCode;
//add this line to get rid of the error
this.cdRef.detectChanges();
}
Я столкнулся с той же проблемой, значение меняется в один из массива в мой компонент. Но вместо того, чтобы обнаруживать изменения на изменения стоимости, я изменил компонент стратегии обнаружения изменений onPush
(который будет обнаруживать изменения на изменения объекта, а не об изменении стоимости).
import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core';
@Component({
changeDetection: ChangeDetectionStrategy.OnPush
selector: -
......
})
Угловой выполняется обнаружение изменения и, когда ее обнаружите, что некоторые ценности, которые были переданы в дочерний компонент был изменен угловые выдает ошибку:
ExpressionChangedAfterItHasBeenCheckederror
подробнее
Для того, чтобы исправить это, мы можем использовать `AfterContentChecked жизни крюк цикл и
import { ChangeDetectorRef, AfterContentChecked} from '@angular/core';
constructor(
private cdref: ChangeDetectorRef) { }
ngAfterContentChecked() {
this.cdref.detectChanges();
}
Ссылаясь на https://blog.angularindepth.com/everything-you-need-to-know-about-the-expressionchangedafterithasbeencheckederror-error-e3fd9ce7dbb4 статья
Так что механизм, лежащий в основе обнаружения изменения на самом деле работает таким образом, что обнаружение изменения и дайджестов проверка выполняются синхронно. Это означает, что, если мы обновим свойства асинхронного значения не будет обновляться, когда цикл проверки работает, и мы не получим ExpressionChanged...
ошибка. Почему мы получаем эту ошибку во время процесса проверки, угловые видит разные значения то, что он записал во время фазы обнаружения изменений. Поэтому, чтобы избежать этого....
Использовать changeDetectorRef
использовании setTimeout. Это позволит выполнить код в другой виртуальной машине в качестве макро-задач. Угловой не увидите эти изменения в ходе процесса проверки, и вы не получите эту ошибку.
setTimeout(() => {
this.isLoading = true;
});
Promise.resolve(null).then(() => this.isLoading = true);
Это позволит создать микро-задач. Микро-задач очереди обрабатывается после текущего синхронный код не будет выполнен, следовательно, обновление в собственность произойдет после этапа верификации.
@HostBinding
может быть запутанным источник этой ошибки.Например, предположим, у вас есть следующие обязательного компонента
// image-carousel.component.ts
@HostBinding('style.background')
style_groupBG: string;
Для простоты, допустим, это свойство обновляется через следующие входные параметры:
@Input('carouselConfig')
public set carouselConfig(carouselConfig: string)
{
this.style_groupBG = carouselConfig.bgColor;
}
В Родительском компонента программно установив его в ngAfterViewInit`
@ViewChild(ImageCarousel) carousel: ImageCarousel;
ngAfterViewInit()
{
this.carousel.carouselConfig = { bgColor: 'red' };
}
Здесь'что происходит :
карусель
до ngAfterViewInit()
(она будет нулевой)style_groupBG = 'красный'
Одно из решений-ввести еще один обрамляющий блок инсайдерской ImageCarousel и установить цвет фона, но тогда вы не'т получить некоторые из преимуществ использования HostBinding (например, позволяет родителю контролировать полном ауте объекта).
Лучшее решение, в родительский компонент, чтобы добавить метод detectchanges() после установки конфига.
ngAfterViewInit()
{
this.carousel.carouselConfig = { ... };
this.cdr.detectChanges();
}
Это может показаться довольно очевидным, изложенных такой, и очень похож на другие ответы, но там'ы тонкое различие.
Рассмотрим случай, когда вы Don'т добавить @HostBinding
до позже в ходе развития. Вдруг вы получаете эту ошибку, и это вовсе'т, кажется, никакого смысла.
Решение, что работал для меня, используя rxjs ``машинопись импорт { начнем, крана, задержка } от 'rxjs/операторы';
Поля // данных, используемых для заполнения в HTML источник: любой;
....
ngAfterViewInit() { это.yourAsyncData. .труба( начнем(нуль), задержка(0), коснитесь((РЭС) => В этом.источник данных = "РЭС") ).подписаться(); } ``
Эта ошибка может быть довольно запутанным, и он'ы легко сделать неправильный вывод о том, когда именно он'ы происходит. Я нахожу это полезным, чтобы добавить много отладки подобные утверждения на территории соответствующих компонентов в соответствующих местах. Это помогает понять поток.
В Родительском положите заявления вроде этого (точную строку 'EXPRESSIONCHANGED' это важно), но другие, чем, что это только примеры:
console.log('EXPRESSIONCHANGED - HomePageComponent: constructor');
console.log('EXPRESSIONCHANGED - HomePageComponent: setting config', newConfig);
console.log('EXPRESSIONCHANGED - HomePageComponent: setting config ok');
console.log('EXPRESSIONCHANGED - HomePageComponent: running detectchanges');
В детстве / услуги / обратные вызовы таймера:
console.log('EXPRESSIONCHANGED - ChildComponent: setting config');
console.log('EXPRESSIONCHANGED - ChildComponent: setting config ok');
Если вы запустите метод detectchanges
вручную добавить лесозаготовок для этого тоже:
console.log('EXPRESSIONCHANGED - ChildComponent: running detectchanges');
this.cdr.detectChanges();
Потом в отладчике Chrome только фильтр 'EXPRESSIONCHANGES'. Это покажет вам точно, потока и того, все, что устанавливается, а также на каком именно угловые точки выдает ошибку.
Вы также можете нажать на серую ссылки ставить точки останова.
Другая вещь, чтобы смотреть, если у тебя аналогично именованные свойства всего приложения (такие как стиль.фон`) убедитесь, что вы'вновь отладку одним вы думаете, что вы - установив его в неясный цвет значение.
Моя проблема проявилась, когда я добавил *ngIf-но это было'т делу. Ошибка была вызвана изменение модели в
{{}}теги затем пытается отобразить измененную модель в*заявление ngIf
позже. Здесь'ы пример:
<div>{{changeMyModelValue()}}</div> <!--don't do this! or you could get error: ExpressionChangedAfterItHasBeenCheckedError-->
....
<div *ngIf="true">{{myModel.value}}</div>
Чтобы исправить проблему, я изменил где я назвал `changeMyModelValue () на место, которое больше смысла.
В моей ситуации я хотел changeMyModelValue()вызывается всякий раз, когда дочерний компонент изменил данные. Для этого требовалось создать и сгенерировать событие в компоненте ребенка, поэтому родитель может справиться с этим (по телефону
changeMyModelValue()`. см https://angular.io/guide/component-interaction#parent-listens-for-child-event
На мой вопрос, я читал на GitHub - "в ExpressionChangedAfterItHasBeenCheckederror при изменении компонент 'номера модели' значение в afterViewInit" и решил добавить ngModel
<input type="hidden" ngModel #clientName />
Это фиксированная моя проблема, я надеюсь, что это помогает кто-то.
У меня была такая ошибка в Ionic3 (который использует угловые 4 как часть его'технология стека с).
Для меня это было этим:
в <Ион-значок [названия]="и getFavIconName()" и></Ион-значок>
Так что я пытался условно изменить тип Ион-значок от пин-код
на Удалить-круг
, в режиме экран работает на.
Я'м предполагаю, что я'll должны добавить *ngIf
вместо этого.
В моем случае, я имел асинхронного собственность в LoadingService с BehavioralSubject isLoading
С помощью [скрыт] модель работает, но *ngIf не
<h1 [hidden]="!(loaderService.isLoading | async)">
THIS WORKS FINE
(Loading Data)
</h1>
<h1 *ngIf="!(loaderService.isLoading | async)">
THIS THROWS ERROR
(Loading Data)
</h1>
Здесь's мои мысли о том, что происходит. Я не читал документацию, но я уверен, что это часть того, почему выводится сообщение об ошибке.
*ngIf="isProcessing()"
При использовании *ngIf, она физически изменяет дом путем добавления или удаления элемента каждый раз при изменении состояния. Так что если состояние изменения, прежде чем он отображается в представление (что весьма возможно в угловой's в мире), ошибка выдается. Смотрите здесь между развитием и режимов производства.
[hidden]="isProcessing()"
При использовании [скрыто] он физически не изменит "дом", а просто прячется
элементс точки зрения, скорее всего, используя
Уссв спину. Элемент по-прежнему существует в DOM, но не видны в зависимости от состояния's стоимостью. Именно поэтому ошибка не возникает при использовании
[скрыто]`.
Я надеюсь, что это помогает кто-то сюда: Мы делаем звонки в ngOnInit в следующем порядке и использовать переменную `displayMain для контроля монтажа элементов в DOM.
компонент.ТС
displayMain: boolean;
ngOnInit() {
this.displayMain = false;
// Service Calls go here
// Service Call 1
// Service Call 2
// ...
this.displayMain = true;
}
и component.html
<div *ngIf="displayMain"> <!-- This is the Root Element -->
<!-- All the HTML Goes here -->
</div>
Я получил эту ошибку, потому что я использую переменную в component.html который не был объявлен в компонент.ТС. Как только я снял часть в HTML, эта ошибка пропала.