ExpressionChangedAfterItHasBeenCheckedError Explained

340

Пожалуйста, объясните мне, почему я продолжаю получать эту ошибку: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked.

Очевидно, я получаю это только в режиме разработки, этого не происходит в моей производственной сборке, но это очень раздражает, и я просто не понимаю преимуществ наличия ошибки в моей среде разработки, которая не отображается в продукте - - вероятно, из-за моего непонимания.

Обычно исправить это достаточно просто, я просто помещаю код, вызывающий ошибку, в setTimeout следующим образом:

setTimeout(()=> {
    this.isLoading = true;
}, 0);

Или принудительно обнаружить изменения с помощью такого конструктора constructor(private cd: ChangeDetectorRef) {}:

this.isLoading = true;
this.cd.detectChanges();

Но почему я постоянно сталкиваюсь с этой ошибкой? Я хочу понять это, чтобы избежать этих хакерских исправлений в будущем.

Кевин ЛеСтардж
источник
12
Все, что вам нужно знать об ошибке ExpressionChangedAfterItHasBeenCheckedError, очень подробно объясняет это поведение
Макс Корецкий
Я также сталкиваюсь с той же проблемой, это происходит только на DEV и влияет только на мои журналы консоли. Вместо того, чтобы вводить новый код в проект, я просто скрываю / блокирую эту ошибку в консоли.
Вайбхав

Ответы:

133

У меня была аналогичная проблема. Глядя на документацию по хукам жизненного цикла , я переключился ngAfterViewInitна, ngAfterContentInitи это сработало.

только я
источник
@PhilipEnc моя проблема была связана с изменением, вызванным изменением DOM. Когда DOM изменится, объект QueryList (полученный из свойства @ContentChildren) будет обновлен, а внутри метода, который это обновление вызвало, изменилось свойство двусторонней привязки. Это создало мою проблему. Перенос этого изменения в двухсвойство, setTimeoutкак показано выше, помогло. Благодарность!
kbpontius 01
1
В моем случае я поместил код, который изменил значение массива сетки primeng в ngAfterContentInit, я поместил код в ngOnInit, и он сработал.
Вибху
ngAfterContentCheckedработает здесь, пока ngAfterContentInitвсе еще выдает ошибку.
ashubuntu 03
ngAfterContentChecked, но проект загружается очень медленно
Ghotekar Rahul
112

Эта ошибка указывает на реальную проблему в вашем приложении, поэтому имеет смысл создать исключение.

При devModeобнаружении изменений после каждого обычного запуска обнаружения изменений добавляется дополнительный поворот, чтобы проверить, изменилась ли модель.

Если модель изменилась между обычным и дополнительным ходом обнаружения изменений, это означает, что либо

  • само обнаружение изменений вызвало изменение
  • метод или геттер возвращает другое значение при каждом вызове

которые оба плохи, потому что неясно, как действовать дальше, потому что модель может никогда не стабилизироваться.

Если Angular запускает обнаружение изменений до тех пор, пока модель не стабилизируется, он может работать вечно. Если Angular не запускает обнаружение изменений, представление может не отражать текущее состояние модели.

См. Также В чем разница между производственным режимом и режимом разработки в Angular2?

Гюнтер Цёхбауэр
источник
5
Как мне избежать появления этой ошибки в будущем? Есть ли другой способ думать о своем коде, чтобы не допустить тех же ошибок?
Кевин ЛеСтардж
27
Обычно это вызвано некоторыми обратными вызовами жизненного цикла, такими как ngOnInitили ngOnChangesдля изменения модели (некоторые обратные вызовы жизненного цикла позволяют изменять модель, другие нет, я не помню точно, какие из них делают или нет). Не привязывайтесь к методам или функциям в представлении, вместо этого привязывайтесь к полям и обновляйте поля в обработчиках событий. Если вам необходимо выполнить привязку к методам, убедитесь, что они всегда возвращают один и тот же экземпляр значения, если на самом деле не было изменений. Обнаружение изменений будет часто вызывать эти методы.
Günter Zöchbauer
Для тех, кто приезжает сюда, кто получает эту ошибку при использовании библиотеки ngx-toaster, вот отчет об ошибке: github.com/scttcper/ngx-toastr/issues/160
rmcsharry
2
Это не обязательно проблема с приложением. changeRef.detectChanges()Доказательство тому, что вызов является решением / подавляет ошибку. Это похоже на изменение состояния внутри $scope.$watch()в Angular 1.
Кевин Бил
1
Я не слишком хорошо знаю Angular 1, но обнаружение изменений в Angular 2 работает по-другому. Вы правы в том, что это не обязательно проблема, но обычно cdRef.detectChanges()необходимо только в некоторых странных крайних случаях, и вам следует внимательно присмотреться, когда вам это нужно, чтобы правильно понять, почему.
Günter Zöchbauer
92

Большое понимание пришло, когда я понял крючки жизненного цикла Angular и их связь с обнаружением изменений.

Я пытался заставить Angular обновить глобальный флаг, привязанный к *ngIfэлементу, и пытался изменить этот флаг внутри ngOnInit()ловушки жизненного цикла другого компонента.

Согласно документации, этот метод вызывается после того, как Angular уже обнаружил изменения:

Вызывается один раз после первого ngOnChanges ().

Таким образом, обновление флага внутри ngOnChanges()не инициирует обнаружение изменений. Затем, как только обнаружение изменений естественным образом сработает снова, значение флага изменится, и выдается ошибка.

В моем случае я изменил это:

constructor(private globalEventsService: GlobalEventsService) {

}

ngOnInit() {
    this.globalEventsService.showCheckoutHeader = true;
}

К этому:

constructor(private globalEventsService: GlobalEventsService) {
    this.globalEventsService.showCheckoutHeader = true;
}

ngOnInit() {

}

и это устранило проблему :)

Кевин ЛеСтардж
источник
3
Моя проблема была похожей. Что я сделал ошибку после долгих часов и определил переменную вне функции и конструктора ngOnInit. Он получает изменения данных от наблюдаемого, который помещается в функцию инициализации. Сделал то же, что и вы, чтобы исправить ошибку.
ravo10
1
Все очень похоже, но я пытался scroll ( router.navigate) при загрузке к фрагменту, если он присутствует в URL-адресе. Этот код изначально был помещен в то место, AfterViewInitгде я получал ошибку, затем я переместился, как вы говорите, в конструктор, но он не соблюдал фрагмент. Переходим к ngOnInitрешенному :) спасибо!
Джоэл Балмер
Что, если мой html привязан к времени возврата геттера как «ЧЧ: ММ» через get ClockValue () {return DateTime.TimeAMPM (new Date ())}, он в конечном итоге отключится, когда минуты изменятся во время обнаружения, как я могу почини это?
Мерьян
Тоже самое. Также обнаружено, что перенос в setInterval()работает также, если он должен срабатывать после другого кода события времени жизни.
Рик Страл,
Получился очень похожий сценарий, хотя мое измененное состояние было не логическим флагом, а некоторым полем перечисления (статуса). Исправление заключалось в том, чтобы обернуть html, ссылающийся на это проблемное поле статуса, «ngIf», который будет проверять какое-то другое уже инициализированное поле.
Юрий Козлов
42

Обновить

Я настоятельно рекомендую в первую очередь начать с самоответа ОП : как следует подумайте о том, что можно сделать в constructorсравнении с тем, что следует делать ngOnChanges().

Оригинал

Это скорее побочное примечание, чем ответ, но оно может кому-то помочь. Я наткнулся на эту проблему, когда пытался сделать наличие кнопки зависимой от состояния формы:

<button *ngIf="form.pristine">Yo</button>

Насколько мне известно, этот синтаксис приводит к тому, что кнопка добавляется и удаляется из DOM в зависимости от условия. Что, в свою очередь, приводит к ExpressionChangedAfterItHasBeenCheckedError.

В моем случае исправление (хотя я не утверждаю, что я понимаю все последствия разницы) заключалось в использовании display: noneвместо этого:

<button [style.display]="form.pristine ? 'inline' : 'none'">Yo</button>
Арно П.
источник
6
Насколько я понимаю, разница между ngIf и стилем заключается в том, что ngIf не включает HTML-код на страницу до тех пор, пока условие не станет истинным, тем самым немного уменьшив «вес страницы», в то время как метод стиля заставляет HTML всегда быть на странице и просто скрывается или отображается в зависимости от значения form.pristine.
user3785010
5
Вы также можете использовать [hidden]вместо очень многословной [style.display]части. :)
Philipp Meissner
2
Почему нет. Хотя, как упомянул @Simon_Weaver в другом комментарии на этой странице, [hidden] не всегда будет иметь такое же поведение, какdisplay: none
Arnaud P
1
Я показывал две разные кнопки (выход / вход) с * ngIf на каждой кнопке, и это вызывало проблему.
GoTo
конструктор был подходящим местом для меня, запустив закусочную материалов
Остин
42

Angular запускает обнаружение изменений, и когда обнаруживает, что некоторые значения, которые были переданы дочернему компоненту, были изменены, Angular выдает следующую ошибку:

ExpressionChangedAfterItHasBeenCheckedError нажмите, чтобы узнать больше

Чтобы исправить это, мы можем использовать AfterContentCheckedкрючок жизненного цикла и

import { ChangeDetectorRef, AfterContentChecked} from '@angular/core';

  constructor(
  private cdref: ChangeDetectorRef) { }

  ngAfterContentChecked() {

    this.cdref.detectChanges();

  }
Lijo
источник
1
Хотя это могло бы решить проблему, разве это не слишком дорого и слишком много для компакт-диска?
Nicky
Я думаю, что это единственный ответ, который устраняет эту ошибку, вызванную передачей значений дочернему элементу. Благодарность!
java-addict301 06
1
@ Никки Да. Каждый раз, когда вы касаетесь экрана в любом месте, вызывается ngAfterContentChecked ()
Мерт Мертс
Это решение помогло мне решить мою проблему с передачей изменений в app.components.ts из дочернего компонента. Спасибо
Scorpy47
мы делаем это в дочернем или родительском компоненте? просто нажмите на ту же проблему и попытайтесь лучше понять корень проблемы.
Тимотронадон
37

Я использую ng2-carouselamos (Angular 8 и Bootstrap 4)

Эти шаги устранили мою проблему:

  1. Осуществлять AfterViewChecked
  2. Добавить constructor(private changeDetector : ChangeDetectorRef ) {}
  3. затем ngAfterViewChecked(){ this.changeDetector.detectChanges(); }
Шахид Хуссейн Аббаси
источник
1
Это помогло. Удивительный!!
Патик Веджани,
Ты спас мне день ... Спасибо!
omostan
34

Были интересные ответы, но я, похоже, не нашел ни одного, соответствующего моим потребностям, ближайшим из которых был @ chittrang-mishra, который относится только к одной конкретной функции, а не к нескольким переключателям, как в моем приложении.

Я не хочу , чтобы использовать [hidden]в своих интересах *ngIfдаже не являясь частью DOM , так что я нашел следующее решение , которое не может быть лучше для всех , как он подавляет ошибку вместо того , чтобы исправить ее, но в моем случае , когда я знаю, окончательный результат правильный, для моего приложения он подходит.

Я реализовал AfterViewChecked, добавил, constructor(private changeDetector : ChangeDetectorRef ) {}а затем

ngAfterViewChecked(){
  this.changeDetector.detectChanges();
}

Я надеюсь, что это поможет другим, как и многие другие помогли мне.

эпер
источник
4
не вызовет ли это бесконечный цикл обнаружения изменений? я имею в виду, вы обнаруживаете изменения после того, как проверили.
Мануэль Азар
@ManuelAzar По-видимому, нет. Это ЕДИНСТВЕННОЕ решение, которое сработало для меня. НАКОНЕЦ немного тишины в моей консоли. Я так устал от всех этих нерелевантных «ошибок» обнаружения изменений.
Джереми Тилль
Что вы подразумеваете под подавлением ошибки? Разве изменение не обнаружено детектором изменения?
Антти Тансканен,
27

Выполните следующие шаги:

1. Используйте ChangeDetectorRef, импортировав его из @ angular / core следующим образом:

import{ ChangeDetectorRef } from '@angular/core';

2. Реализуйте его в constructor () следующим образом:

constructor(   private cdRef : ChangeDetectorRef  ) {}

3. Добавьте следующий метод к вашей функции, которую вы вызываете при таком событии, как нажатие кнопки. Вот так это выглядит:

functionName() {   
    yourCode;  
    //add this line to get rid of the error  
    this.cdRef.detectChanges();     
}
Читтранг Мишра
источник
25

В моем случае у меня была эта проблема в моем файле спецификации при выполнении моих тестов.

Мне пришлось сменить ngIf на [hidden]

<app-loading *ngIf="isLoading"></app-loading>

к

<app-loading [hidden]="!isLoading"></app-loading>
Андре Евангелиста
источник
2
Разница здесь в том, что *ngIfизменяется DOM, добавляется и удаляется элемент со страницы, при этом [hidden]изменяется видимость элемента, не удаляя его из DOM.
Grungondola
5
Но на самом деле это не устранило настоящую проблему ...?
ravo10
21

Я столкнулся с той же проблемой, что и значение в одном из массивов моего компонента. Но вместо того, чтобы обнаруживать изменения при изменении значения, я изменил стратегию обнаружения изменения компонента на onPush(которая будет обнаруживать изменения при изменении объекта, а не при изменении значения).

import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core';

@Component({
    changeDetection: ChangeDetectionStrategy.OnPush
    selector: -
    ......
})
Дирадж
источник
Похоже, это работает для динамического добавления / удаления элементов управления .. есть ли недостатки?
Рикардо Сарачино,
Работает как шарм в ситуации, которая у меня есть, спасибо! Компонент был привязан к «глобальному» объекту, который был изменен в другом месте и вызвал ошибку. В этом компоненте уже был обработчик обновлений, так как при обновлении связанного объекта этот обработчик событий теперь вызывает changeDetectorRef.detectChanges () в сочетании с ChangeDetectionStrategy.OnPush, это работает по желанию без ошибки.
Бернулли IT
@RicardoSaracino Вы нашли недостатки? Я думал о том же самом. Я знаю, как работает OnPush для обнаружения изменений, но мне интересно, есть ли ошибка, которую, возможно, мне не хватает. Я не хочу возвращаться назад.
mtpultz
@RicardoSaracino, да она имеет некоторые недостатки, вы можете обратиться в эту подробную ссылку blog.angular-university.io/onpush-change-detection-how-it-works
Dheeraj
@BernoulliIT Спасибо, я рад, что это сработало для вас.
Дирадж
18

Ссылаясь на статью https://blog.angularindepth.com/everything-you-need-to-know-about-the-expressionchangedafterithasbeencheckederror-error-e3fd9ce7dbb4

Таким образом, механизм обнаружения изменений фактически работает таким образом, что и обнаружение изменений, и дайджесты проверки выполняются синхронно. Это означает, что если мы обновляем свойства асинхронно, значения не будут обновляться во время цикла проверки, и мы не получим ExpressionChanged...ошибку. Причина, по которой мы получаем эту ошибку, заключается в том, что во время процесса проверки Angular видит значения, отличные от тех, которые он записал на этапе обнаружения изменений. Чтобы этого избежать ....

1) Используйте changeDetectorRef

2) используйте setTimeOut. Это выполнит ваш код в другой виртуальной машине как макро-задачу. Angular не увидит эти изменения во время процесса проверки, и вы не получите эту ошибку.

 setTimeout(() => {
        this.isLoading = true;
    });

3) Если вы действительно хотите выполнить свой код на той же виртуальной машине, как

Promise.resolve(null).then(() => this.isLoading = true);

Это создаст микрозадачу. Очередь микрозадач обрабатывается после завершения выполнения текущего синхронного кода, поэтому обновление свойства произойдет после этапа проверки.

ATHER
источник
Можете ли вы использовать вариант №3 с выражением стиля? У меня есть выражение стиля для высоты, которое следует оценивать в последнюю очередь, потому что оно основано на введенном содержимом.
Н-ели
1
Извините, только что увидел ваш комментарий, да, я не вижу причин, почему нет. Так что это должно работать и с изменениями стиля.
ATHER
4

@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' };
}

Вот что происходит:

  • Ваш родительский компонент создан
  • Компонент ImageCarousel создается и назначается carousel (через ViewChild)
  • Мы не можем получить доступ carousel пока ngAfterViewInit()(он будет нулевым)
  • Назначаем конфигурацию, которая устанавливает style_groupBG = 'red'
  • Это, в свою очередь, устанавливает background: red компонент ImageCarousel хоста
  • Этот компонент «принадлежит» вашему родительскому компоненту, поэтому, когда он проверяет наличие изменений, он находит изменение в carousel.style.background и недостаточно умен, чтобы знать, что это не проблема, поэтому он выдает исключение.

Одно из решений - ввести другую оболочку div insider ImageCarousel и установить для нее цвет фона, но тогда вы не получите некоторых преимуществ использования HostBinding (например, разрешение родителю контролировать полные границы объекта).

Лучшее решение в родительском компоненте - добавить detectChanges () после настройки config.

ngAfterViewInit()
{
    this.carousel.carouselConfig = { ... };
    this.cdr.detectChanges();
}

Это может выглядеть довольно очевидным, изложенным таким образом, и очень похоже на другие ответы, но есть небольшая разница.

Рассмотрим случай, когда вы добавляете не @HostBindingраньше, чем во время разработки. Внезапно вы получаете эту ошибку, и это кажется бессмысленным.

Simon_Weaver
источник
2

Вот мои мысли о том, что происходит. Я не читал документацию, но уверен, что это одна из причин появления ошибки.

*ngIf="isProcessing()" 

При использовании * ngIf он физически изменяет DOM, добавляя или удаляя элемент каждый раз, когда изменяется условие. Поэтому, если условие изменится до того, как оно будет отображено в представлении (что очень возможно в мире Angular), выдается ошибка. См. Объяснение здесь между режимами разработки и производства.

[hidden]="isProcessing()"

При использовании [hidden]он не меняет физически, DOMа просто скрывает elementизображение, скорее всего, CSSсзади. Элемент все еще присутствует в модели DOM, но не отображается в зависимости от значения условия. Поэтому при использовании ошибки возникать не будет [hidden].

Кобус
источник
Если isProcessing()это делает АМУ вещь, вы должны использовать !isProcessing()для[hidden]
Матья Шарбонньер
hiddenне «использует CSS в задней части», это обычное свойство HTML. developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/…
Лазар Любенович
2

Пробовал большинство решений, предложенных выше. Только это сработало для меня в этом сценарии. Я использовал * ngIf для переключения неопределенной прогрессивной полосы углового материала на основе вызовов API, и он бросал ExpressionChangedAfterItHasBeenCheckedError.

В рассматриваемом компоненте:

constructor(
    private ngZone: NgZone,
    private changeDetectorRef: ChangeDetectorRef,
) {}

ngOnInit() {
    this.ngZone.runOutsideAngular(() => {
        this.appService.appLoader$.subscribe(value => {
            this.loading = value;
            this.changeDetectorRef.detectChanges();
        });
    });
}

Хитрость заключается в том, чтобы обойти обнаружение изменений углового компонента с помощью ngzone.

PS: Не уверен, что это элегантное решение, но использование ловушки жизненного цикла AfterContentChecked и AfterViewChecked обязательно вызовет проблемы с производительностью, поскольку ваше приложение становится больше, поскольку оно запускается много раз.

Сафал Пиллай
источник
1

Советы по отладке

Эта ошибка может сбивать с толку, и легко сделать неверное предположение о том, когда именно она возникает. Я считаю полезным добавить множество таких отладочных инструкций по всем затронутым компонентам в соответствующих местах. Это помогает понять поток.

В родительских операторах put (важна точная строка 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');

В обратных вызовах child / services / timer:

    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». Это точно покажет вам поток и порядок всего, что устанавливается, а также точно, в какой момент Angular выдает ошибку.

введите описание изображения здесь

Вы также можете щелкнуть серые ссылки, чтобы установить точки останова.

Еще одна вещь, на которую следует обратить внимание, если у вас есть свойства с одинаковыми именами во всем приложении (например, style.background), убедитесь, что вы отлаживаете то, что вы думаете о себе, - установив для него значение неясного цвета.

Simon_Weaver
источник
1

В моем случае у меня было свойство async LoadingServiceс BehavioralSubjectisLoading

Использование модели [hidden] работает, но * ngIf не работает

    <h1 [hidden]="!(loaderService.isLoading | async)">
        THIS WORKS FINE
        (Loading Data)
    </h1>

    <h1 *ngIf="!(loaderService.isLoading | async)">
        THIS THROWS ERROR
        (Loading Data)
    </h1>
Махеш
источник
1

Решение, которое сработало для меня с использованием rxjs

import { startWith, tap, delay } from 'rxjs/operators';

// Data field used to populate on the html
dataSource: any;

....

ngAfterViewInit() {
  this.yourAsyncData.
      .pipe(
          startWith(null),
          delay(0),
          tap((res) => this.dataSource = res)
      ).subscribe();
}
Сандип К. Наир
источник
1
какой был проблемный код? какое здесь решение?
mkb
Привет, @mkb, проблема возникает, ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked.когда изменения значения запускаются при изменении DOM
Сандип К. Наир,
Привет, я имею в виду, что вы здесь сделали, чтобы преодолеть проблему. Вы раньше вообще не использовали rxjs, добавляли delay () или startWith ()? Я уже использую rxjs с различными методами rxjs, но все равно получаю ошибку, надеюсь разгадать
загадку
1
Добавленный delayустраняет ошибку. Работает аналогично setTimeout.
Лазар Любенович
1

У меня была такая ошибка в Ionic3 (который использует Angular 4 как часть своего технологического стека).

Для меня это было так:

<ion-icon [name]="getFavIconName()"></ion-icon>

Итак, я пытался условно изменить тип ионного значка с a pinна a в зависимости от remove-circleрежима, в котором работал экран.

Думаю, мне придется *ngIfвместо этого добавить .

JGFMK
источник
1

Моя проблема была очевидна, когда я добавил, *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

goku_da_master
источник
0

Что касается моей проблемы, я читал github - «ExpressionChangedAfterItHasBeenCheckedError при изменении значения компонента« не модель »в afterViewInit» и решил добавить ngModel

<input type="hidden" ngModel #clientName />

Это устранило мою проблему, надеюсь, это кому-то поможет.

Демодав
источник
2
Где на том сайте написано добавить ngModel. И не могли бы вы объяснить, почему это должно быть полезно?
Peter Wippermann
Когда я отслеживал эту проблему, это заставило меня исследовать ссылку. После прочтения статьи я добавил атрибут, и моя проблема была исправлена. Это полезно, если кто-то столкнется с той же проблемой.
Demodave
0

Надеюсь, это поможет кому-то, кто придет сюда: мы ngOnInitвыполняем сервисные вызовы следующим образом и используем переменную displayMainдля управления монтированием элементов в DOM.

component.ts

  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>
retr0
источник
0

Я получил эту ошибку, потому что использовал переменную в component.html, которая не была объявлена ​​в component.ts. Как только я удалил часть в HTML, эта ошибка исчезла.

Shreekar Hegde
источник
0

Я получил эту ошибку, потому что я отправлял действия redux в модальном режиме, а модальный режим не был открыт в то время. Я отправлял действия в тот момент, когда модальный компонент получал ввод. Поэтому я поместил туда setTimeout, чтобы убедиться, что модальное окно открыто, а затем действия совпадают.

Муним Хабиб
источник
0

Всем, кто борется с этим. Вот способ правильно отладить эту ошибку: https://blog.angular-university.io/angular-debugging/

В моем случае я действительно избавился от этой ошибки с помощью этого [скрытого] хака вместо * ngIf ...

Но предоставленная мной ссылка позволила мне найти ВИНОВНЫХ * ngIf :)

Наслаждаться.

Deunz
источник
Использование hiddenвместо ngIfне является взломом и вообще не решает сути проблемы. Вы просто маскируете проблему.
Лазар Любенович
2
так что это взлом. грязное исправление, которого следует избегать
Том
-2

Решение ... службы и rxjs ... эмиттеры событий и привязка свойств используют rxjs .. вам лучше реализовать его самостоятельно, больше контроля, легче отлаживать. Помните, что эмиттеры событий используют rxjs. Просто создайте сервис и внутри наблюдаемого, пусть каждый компонент подписывается на наблюдателя и либо передает новое значение, либо значение cosume по мере необходимости.

user998548
источник
1
Это не только не ответ на вопрос, но и ужасный совет. Ребята, пожалуйста, не переопределяйте rxjs самостоятельно только потому, что вы получаете ошибки компакт-диска Angular. :)
Лазарь Любенович
-7

Какое-то время я боролся с этой проблемой, в первую очередь при выполнении тестов в своей среде разработки. Мне удалось решить проблему с помощью простого setTimeout для ответа на вызов службы!

davida227
источник