Angular 4 - formcontrol.setValue() 在 OnChanges() 中

Angular 4 - formcontrol.setValue() inside OnChanges()

使用 Angular 4. 我有一个 paging.component 从中获取 page 编号和 pageSize父组件(获取数据后)。

paging.component 将使用 OnChanges 生命周期挂钩查找对 @Input 的更改。

paging.component 还有一个 <select> 输入,您可以在其中更改 pageSize

OnInit 阶段,<select> 设置为从父组件传入的 pageSize

如果将 pageSize 更改为 <select>,一切正常,但有时我也想更改 pageSize 从父组件到不同的值(如原始值)。

但是,当我从父组件更改 pageSize 时,它不会更改 <select> 输入。 (即使其他一切似乎都正常工作)。

我尝试将以下代码添加到 ngOnChanges 方法中:

if (this.pageSizeFG) {
    this.pageSizeCtrl.setValue(this.pagesize);
}

但是,这会产生错误:

ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'false'. Current value: 'true'.

如果我尝试转到其他页面,分页似乎也会不断将自身重置为第 1 页。

我研究了其他一些生命周期挂钩,ChangeDetectorRefngZone,但这些似乎使问题变得更糟。

我创建了一个 plnkr here 来演示错误。

如果您转到 paging.component.ts 并注释掉带有 this.pageSizeCtrl.setValue(this.pagesize); 的行,那么一切正常 除了 <select> 没有更新。

这是由 select 元素上的 ngModelChange 事件 + ngOnchanges 生命周期方法引起的。

<select (ngModelChange)="setPageSize($event)">...</select>

发生的事情是

  1. you pass in a new input to paging.component
  2. ngOnChanges fires
  3. within ngOnChanges, this.pageSizeCtrl.setValue(this.pagesize) fires
  4. This causes the ngModelChange event to fire (setPageSize)
  5. setPageSize emits to the parent component
  6. parent changes input which causes ngOnChanges to fire again.

所以这一切都会导致表达式已更改错误。

为了解决这个问题,我会使用 change 事件而不是 ngModelChange

<select (change)="setPageSize()">...</select>

这样 setValue() 不会触发 setPageSize() 事件。您还需要更新 setPageSize() 发出 pageSize 属性.

的方式
setPageSize() {
    // get pageSizeCtrl value programatically
    let pageSize = +this.pageSizeCtrl.value;
    this.pagechange.emit({ page: 1, pageSize: pageSize });
}

这是一个带有修复的工作 plnkr (http://plnkr.co/edit/zJEIYJzG5OGRXIfA77Qz?p=preview)