在我的 table 组件中检查后表达式发生了变化
Expression has changed after it was checked in my table component
我构建了一个 table 组件 ez-table,它允许您将模板传递给列以呈现当前项目。这一切都很好,但由于某种原因,当我有一个表单字段具有依赖于另一个表单字段中的数据的验证属性时,我收到错误
Error: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked.
Previous value: 'ng-valid: true'. Current value: 'ng-valid: false'.
如果更改一个字段的值会使另一个字段无效。
在以下示例中,如果行中的一个字段具有值,则另一个字段变为必填。
<form #form="ngForm">
<ez-table [data]="rows">
<ez-column heading="Val 1" property="val1">
<ng-template let-row let-i="index">
<input [name]="'val1_' + i" [(ngModel)]="row.val1" [required]="!!row.val2">
</ng-template>
</ez-column>
<ez-column heading="Val 2" property="val2">
<ng-template let-row let-i="index">
<input [name]="'val2_' + i" [(ngModel)]="row.val2" [required]="!!row.val1">
</ng-template>
</ez-column>
</ez-table>
Valid: {{ form.valid | json }}
</form>
我无法理解为什么我的 table 组件会发生这种情况,而我可以在没有该组件的情况下执行完全相同的操作并且不会出现错误。
这个 table 做的事情完全一样,但在一个字段中输入数据不会触发错误,但会更新表单的有效性。
<form #form2="ngForm">
<table>
<thead>
<tr><th>Val 1</th><th>Val 2</th></tr>
</thead>
<tbody>
<tr *ngFor="let row of rows2;index as i">
<td>
<ng-container *ngTemplateOutlet="editTemplate1;context:{ $implicit: row, index: i }">
</ng-container>
</td>
<td>
<ng-container *ngTemplateOutlet="editTemplate2;context:{ $implicit: row, index: i }">
</ng-container>
</td>
</tr>
</tbody>
</table>
Valid: {{ form2.valid | json }}
<ng-template #editTemplate1 let-row let-i="index">
<input [name]="'val1_' + i" [(ngModel)]="row.val1" [required]="!!row.val2">
</ng-template>
<ng-template #editTemplate2 let-row let-i="index">
<input [name]="'val2_' + i" [(ngModel)]="row.val2" [required]="!!row.val1">
</ng-template>
</form>
这是 StackBlitz
https://stackblitz.com/edit/angular-k58bmn?file=src/app/app.component.html
table 组件的源代码位于
在您的组件中添加 detectChanges。
修复:https://stackblitz.com/edit/angular-xsgyqj
import { Component, ChangeDetectorRef } from "@angular/core";
@Component({
selector: "my-app",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.css"]
})
export class AppComponent {
rows = Array.from({ length: 5 }, () => ({}));
rows2 = Array.from({ length: 5 }, () => ({}));
constructor(private changeDetection: ChangeDetectorRef) {}
ngAfterContentChecked() {
this.changeDetection.detectChanges();
}
}
我构建了一个 table 组件 ez-table,它允许您将模板传递给列以呈现当前项目。这一切都很好,但由于某种原因,当我有一个表单字段具有依赖于另一个表单字段中的数据的验证属性时,我收到错误
Error: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked.
Previous value: 'ng-valid: true'. Current value: 'ng-valid: false'.
如果更改一个字段的值会使另一个字段无效。
在以下示例中,如果行中的一个字段具有值,则另一个字段变为必填。
<form #form="ngForm">
<ez-table [data]="rows">
<ez-column heading="Val 1" property="val1">
<ng-template let-row let-i="index">
<input [name]="'val1_' + i" [(ngModel)]="row.val1" [required]="!!row.val2">
</ng-template>
</ez-column>
<ez-column heading="Val 2" property="val2">
<ng-template let-row let-i="index">
<input [name]="'val2_' + i" [(ngModel)]="row.val2" [required]="!!row.val1">
</ng-template>
</ez-column>
</ez-table>
Valid: {{ form.valid | json }}
</form>
我无法理解为什么我的 table 组件会发生这种情况,而我可以在没有该组件的情况下执行完全相同的操作并且不会出现错误。
这个 table 做的事情完全一样,但在一个字段中输入数据不会触发错误,但会更新表单的有效性。
<form #form2="ngForm">
<table>
<thead>
<tr><th>Val 1</th><th>Val 2</th></tr>
</thead>
<tbody>
<tr *ngFor="let row of rows2;index as i">
<td>
<ng-container *ngTemplateOutlet="editTemplate1;context:{ $implicit: row, index: i }">
</ng-container>
</td>
<td>
<ng-container *ngTemplateOutlet="editTemplate2;context:{ $implicit: row, index: i }">
</ng-container>
</td>
</tr>
</tbody>
</table>
Valid: {{ form2.valid | json }}
<ng-template #editTemplate1 let-row let-i="index">
<input [name]="'val1_' + i" [(ngModel)]="row.val1" [required]="!!row.val2">
</ng-template>
<ng-template #editTemplate2 let-row let-i="index">
<input [name]="'val2_' + i" [(ngModel)]="row.val2" [required]="!!row.val1">
</ng-template>
</form>
这是 StackBlitz
https://stackblitz.com/edit/angular-k58bmn?file=src/app/app.component.html
table 组件的源代码位于
在您的组件中添加 detectChanges。
修复:https://stackblitz.com/edit/angular-xsgyqj
import { Component, ChangeDetectorRef } from "@angular/core";
@Component({
selector: "my-app",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.css"]
})
export class AppComponent {
rows = Array.from({ length: 5 }, () => ({}));
rows2 = Array.from({ length: 5 }, () => ({}));
constructor(private changeDetection: ChangeDetectorRef) {}
ngAfterContentChecked() {
this.changeDetection.detectChanges();
}
}