在 textarea 上使用 [(ngModel)] 绑定时如何避免 ExpressionChangedAfterItHasBeenCheckedError

Posted

技术标签:

【中文标题】在 textarea 上使用 [(ngModel)] 绑定时如何避免 ExpressionChangedAfterItHasBeenCheckedError【英文标题】:How to avoid ExpressionChangedAfterItHasBeenCheckedError when using [(ngModel)] binding on textarea 【发布时间】:2018-04-05 19:07:30 【问题描述】:

我创建了一个组件,它表示用于修改对象细节的表单。对象存在于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

该错误与&lt;textarea&gt; 没有直接关系,因为它表示该值从false 变为true,因此似乎与表单上的valid 属性有关,如提示的那样here.

有趣的是,我可以通过修改&lt;textarea&gt;&lt;/textarea&gt; 的内容来避免该错误,例如在内容后放置一个空格:

<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 在不触发此错误的情况下相互交谈的正确方式是什么?

【问题讨论】:

从输入中删除 value="item.name" 因为它正在无限循环。 ngModel就够了 【参考方案1】:

如果你用ngModel那么item.description没用,应该够了:

<mat-form-field class="full-width">
   <textarea id=description matInput [(ngModel)]="item.description" placeholder="Description"></textarea>
</mat-form-field>

【讨论】:

那行不通。不在&lt;textarea&gt; 中,也不在任何&lt;input&gt;s 中。 这是否意味着 mat-form-field 没有被正确实施? 我的意思是,它可以正确渲染,但显然有些地方不对,因为没有value="item.&lt;field&gt;",该字段就没有任何价值。 我认为您必须指定name 属性才能使其在没有值和插值的情况下工作。【参考方案2】:

如果有人因为遇到类似问题而发现自己在这里:

首先要检查的是确保[(ngModel)]="value" 的使用如文档中所示。如果没有,请确保您已导入 FormsModuleAngular Material 文档忽略了提及它,但 ngModel 没有它就无法工作。

另见Why (ngModel) is not working?

【讨论】:

【参考方案3】:

这个错误把我逼疯了,它只是在升级到 Angular 5 后才出现。就我而言,我没有使用[(ngModel)]。我仅将 textarea 用于显示目的(以获得 Material 外观)。尽管如此,这对于像我一样无休止地搜索的其他人可能会有所帮助。

我发现如果你绑定到 textarea 的 [value] 属性而不是使用插值 ,错误就会消失。

代替:&lt;textarea&gt;value&lt;/textarea&gt;

做:&lt;textarea [value]="value"&gt;&lt;/textarea&gt;

&lt;input&gt; 没有任何问题,因为它是单标签元素,因此必须使用属性绑定而不是插值。 (需要说明的是,您只需要将插值与value 一起使用,因为您绑定到只评估一次的属性。绑定到[value],这是一个属性,您不再需要 . 请参阅 Angular 文档,其中解释得很清楚。)

我怀疑通过插值,angular 在第一个摘要循环中将表单设置为false,在第二个摘要中设置为true,当它识别出该值时。使用[value] 属性绑定,它可以识别第一个摘要中的值。

无论如何,它都有效。

【讨论】:

谢谢,这让我发疯了。你的建议解决了它。 这不适用于使用 Angular 7 的我,尽管它确实帮助我在 &lt;mat-form-field&gt; 中使用 &lt;ng-container&gt; 时发现了我的问题。 我也与第一行有关“这个错误让我发疯了”。我的是一个文本框,幸运的是它是只读的。所以我把它改成了 [value]。【参考方案4】:

我遇到了这个错误:

ExpressionChangedAfterItHasBeenCheckedError ... Previous value: 'aria-describedby: null' Current value: 'aria-describedby: mat-error-22'

问题是我在创建表单之后和加载 mat-form-field 组件之前立即手动验证我的表单。就我而言,我实际上不必验证我的表单,因此我将其删除。

【讨论】:

【参考方案5】:

该问题主要是由于在视图初始化期间为组件的相同参数设置了两个不同的值。

angular-university blog 上对问题和替代解决方案有很长的解释。

【讨论】:

以上是关于在 textarea 上使用 [(ngModel)] 绑定时如何避免 ExpressionChangedAfterItHasBeenCheckedError的主要内容,如果未能解决你的问题,请参考以下文章

用于 textarea 的 ngModel 不能在角度 2 中工作

Textarea 中每行的最大长度

Ionic 3 ion-textarea 换行问题

在 Angular 的 INPUT 元素上使用 ngModel 中的管道

ionic 3 单击按钮后从 ion-textarea 获取文本

如何在离子无线电元件上使用 ngModel?