问题
I have a parent component and i am passing some HTML from it to a child common component using @ViewChild().
When Child component loads up a popup. Console throws below error.
"ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'ngIf: undefined'. Current value: 'ngIf: this is description'. It seems like the view has been created after its parent and its children have been dirty checked. Has it been created in a change detection hook ?"
I am using { NgbModal } from '@ng-bootstrap/ng-bootstrap';
This is the code.
Update - This parent component is called as app-parent-component in another parent html file.
Parent Component
@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';
Parent HTML
<ng-template #templateToLoad>
<div class="someClass">This data will be shown on Popup without any error.
</div>
</ng-template>
CommonChildPopup Component
@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>
The above console error is for this line ngIf="description". If i remove this line, same error will come for next line. Please help.
回答1:
You're trying to update the property values in a lifecycle hook after they have been previously checked in the parent component.
The recommended solution is to open the modal on a button click / another user triggered event, or if you need to open it after the view is initialized you can use the setTimeout() that will skip a tick
ngAfterViewInit() {
setTimeout(() => this.openPopup());
}
Working plunker : https://plnkr.co/edit/FVV7QVp620lIGJwEhN6V?p=preview
A very nice and detailed explanation about this error : https://blog.angularindepth.com/everything-you-need-to-know-about-the-expressionchangedafterithasbeencheckederror-error-e3fd9ce7dbb4
回答2:
ExpressionChangedAfterItHasBeenCheckedError
: Expression has changed after it was checked. Previous value: 'ng-untouched: true'
. Current value: 'ng-untouched: false'
.
setTimeout
trick doesn't work for subscribing for reactive form either. The following workaround should work for me
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'
});
}
回答3:
In my case the error was happening in an Angular 4 application. The application needed to open an ng-bootrap modal when the user selected a value from a dropdown in a reactive form. Using the setTimeout
workaround did not work. However, the solution described in the below link - i.e. setting the control to touched (by calling markAsTouched()
on the control) resolved the error.
This issue is in Angular as described here.
来源:https://stackoverflow.com/questions/49292932/expression-has-changed-error-on-opening-a-modal-popup-inside-a-component