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,因此似乎与表单上的有效属性相关,如here所示.
有趣的是,我可以通过修改< textarea>< / textarea>的内容来避免错误.例如在内容后面加一个空格:
<textarea ...>{{item.description}} </textarea>
但是只有当item.description不为null时才有效.当它为null然后我再次得到错误.
我正在从另一个子组件触发对selectedItem的更改,该组件也对selectedItem具有双向绑定.当用户选择项目时,新项目将向上流向应用程序,然后返回到详细信息组件.
我看过Everything you need to know about the ‘ExpressionChangedAfterItHasBeenCheckedError’ error文章.引用文章“我不建议使用它们,而是重新设计您的应用程序”.
大!怎么样?如何构造事物以便控件A用于选择项目,控件B用于编辑它?控件A和B在没有触发此错误的情况下相互通信的正确方法是什么?
解决方法
我发现如果你绑定到textarea的[value]属性而不是使用插值{{}},那么错误就会消失.
而不是:< textarea> {{value}}< / textarea>
执行:< textarea [value] =“value”>< / textarea>
您对< input>没有任何问题因为它是单标签元素,因此必须使用属性绑定而不是插值. (要清楚的是,您只需要将插值与值一起使用,因为您绑定到仅评估一次的属性.绑定到[value],这是一个属性,您不再需要{{}}.请参阅角度文档,其中非常清楚地解释了这一点.)
我怀疑使用插值时,angular会在第一个摘要周期将表单设置为false,而在第二个摘要时将其设置为true,以便识别该值.使用[value]属性绑定,它会识别第一个摘要上的值.
无论如何,它都有效.