我创建了一个表示用于修改对象详细信息的表单的组件。该对象存在于app.component.ts
:
export class AppComponent {
selectedItem: Item;
}
它通过双向绑定传递到app.component.html
的组件中,如下所示:
<item-details [(item)]="selectedItem"></item-details>
在组件中,Item
的各个字段绑定到输入控件,以允许用户更新数据,例如:
<mat-form-field class=name>
<input matInput [(ngModel)]="item.name" value="{{item.name}}" required placeholder="Name">
<mat-error>Item name can not be left blank</mat-error>
</mat-form-field>
一切顺利,直到我到达textarea:
<mat-form-field class="full-width">
<textarea id=description matInput [(ngModel)]="item.description" placeholder="Description">{{item.description}}</textarea>
</mat-form-field>
它工作,但它引发了一个例外:
ExpressionChangedAfterItHasBeenCheckedError
该错误与<textarea>
没有直接关联,因为它表示该值从false
变为true
,因此似乎与valid
相关表格上的财产,如here所示。
有趣的是,我可以通过修改<textarea></textarea>
的内容来避免错误,例如在内容后加一个空格:
<textarea ...>{{item.description}} </textarea>
但只有在item.description
不是null
时才有效。当它是null
时,我再次收到错误。
我从另一个子组件触发对selectedItem
的更改,该子组件在selectedItem
上也具有双向绑定。当用户选择一个项目时,新的Item
会向上流向应用,然后返回到详细信息组件。
我已阅读Everything you need to know about the 'ExpressionChangedAfterItHasBeenCheckedError' error条。引用文章“我不建议使用它们,而是重新设计您的应用程序”。
大!怎么样?如何构造事物以便控件A用于选择Item
,控件B用于编辑它?控件A和B在没有触发此错误的情况下相互通信的正确方法是什么?
答案 0 :(得分:9)
这个错误让我非常疯狂,它只在升级到Angular 5之后才显露出来。就我而言,我没有使用[(ngModel)]
。我正在使用textarea仅用于显示目的(以获得材料的外观和感觉)。然而,这可能对其他人像我一样无休止地搜索有所帮助。
我发现如果你绑定到textarea的[value]
属性而不是使用插值{{}}
,那么错误就会消失。
而不是:<textarea>{{value}}</textarea>
执行:<textarea [value]="value"></textarea>
您对<input>
没有任何问题,因为它是单标记元素,因此必须使用属性绑定而不是插值。 (要清楚的是,您只需要使用插值和value
,因为您绑定的属性只被评估一次。绑定到[value]
,这是一个属性,您不再需要{{}}
。请参阅角度文档,其中非常清楚地解释了这一点。)
我怀疑使用插值时,angular会在第一个摘要周期将表单设置为false
,并在识别值时将其设置为第二个摘要true
。使用[value]
属性绑定,它会识别第一个摘要上的值。
无论如何,它都有效。
答案 1 :(得分:0)
如果您使用的是ngModel
,那么{{item.description}}
就没用了,应该就够了:
<mat-form-field class="full-width">
<textarea id=description matInput [(ngModel)]="item.description" placeholder="Description"></textarea>
</mat-form-field>
答案 2 :(得分:0)
如果有人发现自己,因为他们有类似的问题:
要检查的第一件事是确保[(ngModel)]="value"
的使用如文档中所示。如果没有,请确保已导入FormsModule
。 Angular Material 文档忽略了它,但ngModel
没有它就无法工作。
答案 3 :(得分:0)
我遇到了这个错误:
ExpressionChangedAfterItHasBeenCheckedError ... Previous value: 'aria-describedby: null' Current value: 'aria-describedby: mat-error-22'
问题是在创建表单之后以及在加载mat-form-field组件之前,我正在立即手动验证表单。就我而言,我实际上不必验证我的表单,因此我将其删除。
答案 4 :(得分:0)
该问题主要是由于在视图初始化期间为组件的同一参数设置了两个不同的值。
angular-university blog 上对问题和替代解决方案有很长的解释。