通过调用" ChangeDetectorRef :: detectChanges()"避免“表达式在检查后发生了变化”错误

时间:2017-12-07 19:36:38

标签: angular typescript data-binding

我正在尝试在模型上应用管道时在日期输入上实现双向数据绑定:

<!-- The name variable is retrieved within the HTML from a loop expression -->
<input matInput [matDatepicker]="datePicker" placeholder="{{label}}" formControlName="{{name}}"
[ngModel]="data[name] | date"
(ngModelChange)="handleDateChange(data[name], $event)" >

我的组件看起来像:

//...
private data: any;

constructor(private cdRef:ChangeDetectorRef) { }

handleDateChange(field: any, date: any) {
    field = date; // The code is simplified, there is more handling with the date field
    this.cdRef.detectChanges();
}

基于this post,上面的代码只能运行this.cdRef.detectChanges();如果我将其删除,我会收到以下错误: 检查后表情发生了变化

我的问题比上述实施更具体。我想知道处理表达式在检查后发生了变化错误的最佳做法是什么?打电话给cdRef.detectChanges()是个好主意吗?

3 个答案:

答案 0 :(得分:3)

您是否尝试直接分配更改事件的值?

<!-- The name variable is retrieved within the HTML from a loop expression -->
<input matInput [matDatepicker]="datePicker" placeholder="{{label}}" formControlName="{{name}}"
[ngModel]="data[name] | date"
(ngModelChange)="data[name] = $event" >

使用这种方法,您可以在ngModel上使用管道,并保持简单,就像它正在执行常规[(ngModel)]双向绑定一样。无需额外的处理程序。

修改

发生这种情况的另一个原因可能是尝试将模板驱动方法与反应形式方法混合使用。我假设你不想两者兼顾,对吗?通过查看formControlName属性,它可能会告诉我您正在尝试混合使用这两种方法,因此您肯定会遇到此问题。

原因是因为只要模板驱动方法发生更改,ngModel就会更新值,同时响应式表单方法也会更新同一属性上的值。因为这是并行发生的,所以当Angular在开发模式下运行第二次检查更改时会触发错误。属性更新应仅由其中一种方法处理。

检查发生这种情况的方案here

答案 1 :(得分:2)

(ngModelChange)="handleDateChange(data[name], $event)"

如果在handleDateChange(data[name], $event)中添加调试行,则表示日期可能未定义,这是不正确的。你必须把$event作为第一个参数。

你没有&#39;需要将data[name]传递到handleDateChange(),您的组件中才能访问data。你需要做的是:

xxx.component.html

(ngModelChange)="handleDateChange($event)"

xxx.component.ts:

handleDateChange(event: any) {
  // change your data
  this.data[this.name] = event;
}

答案 2 :(得分:0)

尝试更改此

<input matInput [matDatepicker]="datePicker" placeholder="{{label}}" formControlName="{{name}}"
[ngModel]="data[name] | date"
(ngModelChange)="handleDateChange(name, $event)" >

  ...


  handleDateChange(field, date) {
    this.data[field] = date;
  }

this.cdRef.detectChanges();

如果您需要任何解释,为什么表达式在检查后发生了变化以及为什么{{1}}有帮助