Выражение изменило ошибку при открытии модального всплывающего окна внутри компонента

У меня есть родительский компонент, и я передаю некоторый HTML из него в общий дочерний компонент, используя @ViewChild().

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

"ExpressionChangedAfterItHasBeenCheckedError: выражение изменилось после проверки. Предыдущее значение: "ngIf: undefined". Текущее значение: "ngIf: это описание". грязно проверено. Было ли оно создано в хуке обнаружения изменений ?"

Я использую { NgbModal } из '@ng-bootstrap/ng-bootstrap';

Это код.

Обновление. Этот родительский компонент вызывается как app-parent-component в другом родительском HTML-файле.

Родительский компонент

@ViewChild('templateToLoad') templateToLoad;


constructor(private modalService: NgbModal, private ChangeDetector: ChangeDetectorRef) {
}

ngOnInit() {
    this.openPopup();
}

ngAfterViewInit() {
    this.ChangeDetector.detectChanges();
}

private openPopup() {
    const modalPrompt = this.modalService.open(CommonChildModalComponent, {windowClass: 'modal-prompt fade-in-down'});
    modalPrompt.componentInstance.title = 'Title';
    modalPrompt.componentInstance.contentTemplate = this.templateToLoad;
    modalPrompt.componentInstance.originContext = this;
    modalPrompt.componentInstance.description = 'ABC';

Родительский HTML

<ng-template #templateToLoad>
  <div class="someClass">This data will be shown on Popup without any error.
  </div>
</ng-template>

Компонент CommonChildPopup

@Input() title?: string;
@Input() description?: string;
@Input() originContext: any;
@Input() contentTemplate?: any;

constructor(public activeModal: NgbActiveModal) {
}

ngOnInit() {
    console.log('I am here in CommonModalComponent ngOnInit');
}

CommonChildPopup HTML

<div class="modal-header">
  <h4 class="modal-title">{{title}}</h4>
</div>

<div class="modal-body pb-3" [class.dimmer]="simulateLoading">
  <p *ngIf="description">{{description}}</p>
  <ng-container *ngTemplateOutlet="contentTemplate"></ng-container>

Приведенная выше ошибка консоли относится к этой строке ngIf="description". Если я удалю эту строку, такая же ошибка появится для следующей строки. Пожалуйста помоги.


person Aakash Kumar    schedule 15.03.2018    source источник
comment
ошибка связана с изменением значения переменной после того, как angular проверил содержимое. Итак, какую бы логику вы ни применяли для изменения значений, делайте это внутри ngAfterContentChecked()   -  person CruelEngine    schedule 15.03.2018
comment
Я не меняю здесь никаких значений или какой-либо логики. Какие бы значения я ни устанавливал в родительском компоненте, они должны быть загружены, но каким-то образом он вызывает компонент chid и видит неопределенное, и второй раз он находит правильные значения.   -  person Aakash Kumar    schedule 15.03.2018


Ответы (3)


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

Рекомендуемое решение - открыть модальное окно при нажатии кнопки/другом событии, инициированном пользователем, или, если вам нужно открыть его после инициализации представления, вы можете использовать setTimeout(), который пропустит тик

ngAfterViewInit() { setTimeout(() => this.openPopup()); }

Работающий плункер: https://plnkr.co/edit/FVV7QVp620lIGJwEhN6V?p=preview

Очень хорошее и подробное объяснение этой ошибки: >https://blog.angularindepth.com/everything-you-need-to-know-about-the-expressionchangedafterithasbeencheckederror-error-e3fd9ce7dbb4

person Lucian Moldovan    schedule 15.03.2018
comment
Я пробовал, но все та же ошибка. Я добавил эту строку, чтобы исправить ошибку, но все равно ничего. :( - person Aakash Kumar; 15.03.2018
comment
я новичок в этом. Я не знаю, как сделать рабочее приложение с этим кодом на plunker. :( - person Aakash Kumar; 15.03.2018
comment
Большое спасибо .. это действительно помогло мне. - person Aakash Kumar; 16.03.2018

ExpressionChangedAfterItHasBeenCheckedError: Выражение изменилось после проверки. Предыдущее значение: 'ng-untouched: true'. Текущее значение: 'ng-untouched: false'.

setTimeout трюк не работает и для подписки на реактивную форму. Следующий обходной путь должен работать для меня

HTML

<select [ngModel]="countryId"  #ngModelDir="ngModel"
      (ngModelChange)="fileChangeEvent($event, ngModelDir)">

ts

import { NgModel } from '@angular/forms';
...
fileChangeEvent(event: any, ngModelDir: NgModel) {
  ngModelDir.control.markAsTouched();
  const modalRef = this.modalService.open(MymodalComponent, {
    keyboard: false,
    backdrop: 'static'
  });
}
person Arul    schedule 28.02.2019
comment
Это работает! Но я хочу знать, почему? и в чем причина, потому что управление не трогается.... - person ismaestro; 04.03.2019
comment
@Ismaestro Когда мы открываем модальное окно, элемент формы теряет фокус. Поэтому необходимо пометить элемент управления в группе форм как затронутый явно. - person Arul; 05.03.2019
comment
Все еще ! Этот код не работает в случае библиотеки ng-select для потока редактирования, когда у вас есть несколько выбранных значений, поступающих в поток редактирования. - person Aakash Kumar; 05.03.2019

В моем случае ошибка происходила в приложении Angular 4. Приложению необходимо было открывать модальное окно ng-bootrap, когда пользователь выбирал значение из раскрывающегося списка в реактивной форме. Использование обходного пути setTimeout не сработало. Однако решение, описанное в приведенной ниже ссылке, т.е. установка элемента управления на касание (путем вызова markAsTouched() в элементе управления), устранило ошибку.

Эта проблема в Angular описана здесь.

person Atif Majeed    schedule 04.10.2018