首页 > 解决方案 > Angular - 如何处理双重绑定和验证?

问题描述

当试图实现一个复杂的组件(日期和时间输入)时,这个问题就开始了,父组件拥有一个明确的“状态”(复合时间戳)。父组件使用一个子组件(一个数字字段),它采用双重绑定来更新状态的相关部分。

孩子不知道(也不应该)完整的验证逻辑,所以它会(通过一个Output属性)发出它所有的值变化。其中一些值将导致无效状态(例如时间戳超过允许的最大值)。在这种情况下,我想停止事件的传播,并让父组件“重置”子组件的状态。

但是,这不会发生,因为(就更改检测而言)父级的状态没有改变,所以input子级的属性没有重置。

我在Stackblitz 上将这个问题降到最低。

然而,问题的核心很简单:

@Component({
  selector: "my-child",
  template: `
    Value on the child: {{ value }}<br />
    <button (click)="value = value + 1">Increment</button>
  `
})
export class ChildComponent {
  private _value = 0;
  get value() {
    return this._value;
  }
  @Input() set value(v: number) {
    if (v !== this._value) {
      this._value = v;
      this.valueChange.emit(v);
    }
  }

  @Output() valueChange = new EventEmitter<number>();
}

@Component({
  selector: "my-app",
  template: `
    <div>The value on the parent is: {{ parentValue }}</div>
    <my-child [(value)]="parentValue"></my-child>
  `
})
export class AppComponent {
  _parentValue = 0;
  get parentValue() {
    return this._parentValue;
  }
  set parentValue(v: number) {
    // discard values more than 5 because they are "invalid"
    // probably I shouldn't just "return", but what to do?
    if (this.isInvalid(v)) return;
    this._parentValue = v;
  }

  isInvalid(v: number) {
    return v > 5;
  }
}

单击子项将使子项value超过 5,而parentValue将保持其最大值为 5。并且,由于parentValue没有更改,因此更改检测不会在子组件中设置 input 属性。

让父母完全拥有状态并在适当时“重置”它的孩子的最佳方式应该是什么?我可以使用ViewChildren并破解它,但实际情况显然要复杂得多,我正在寻找一个可以遵循的一般模式。

标签: angulartypescript

解决方案


推荐阅读