当绑定到的值不变时,强制更改检测

时间:2019-05-05 18:37:21

标签: angular typescript data-binding

我有一个组件可以对输入控件中的更改做出反应,并通过删除某些字符来对其重新格式化。设置完成后,备份字段中存储的值可能会更改或不会更改。在第一种情况下,一切正常,但是如果删除的字符映射到先前的值,则不会检测到任何更改,并且组件也不会更新。导致包含可移动字符的值停留在输入框中。

如何强制通过 [(ngModel)] 绑定到后备字段的输入框实际更新将其输入值更改为 get prop()设施?

export class RowConfig {
  constructor(public amount = 0, ...) { }

  get rendition() {
    let output = "";
    if (this.amount !== null && this.amount !== undefined)
      output = ("" + this.amount)
        .replace(/(\d)(?=(\d{3})+(?!\d))/g, "$1 ");
    return output;
  }
  set rendition(input: string) {
    const negative = input.match(/^[-]/);
    const digits = input.replace(/\D/g, "");
    let output = null;
    if (digits)
      output = +digits * (negative ? -1 : 1);
    this.amount = output;
  }
}

绑定是这样完成的。

<input #amount type="text"
       (keyup)="onKeyUp($event)"
       [(ngModel)]="config.rendition">

我尝试使用声明为in docs markForCheck() detectChanges() onKeyUp 中执行检测更改。没什么不同。

如何强制输入框实际清除当前内容并将其替换为bound属性的实际值?

Blitzy上的可播放演示。)

1 个答案:

答案 0 :(得分:2)

即使最终值与现有值相同,也要强制视图更新的技巧是在设置原始值(可能是无效的值)后首先调用ChangeDetectorRef.detectChanges(),然后设置正确的值值。

例如,如果您有一个仅接受数字的文本字段,并且如果处理是在组件代码中完成的,则可以按以下方式实现设置器:

private _numericString: string;

get numericString() {
  return this._numericString;
}
set numericString(value) {
  this._numericString = value;     // <------------------------ Set the raw value
  this.changeDetectorRef.detectChanges();   // <--------------- Trigger change detection
  this._numericString = value.replace(/[^\d]/gi, ""); // <----- Set the corrected value
}

有关演示,请参见this stackblitz


在您的实际代码中,config.Rendition被定义为单独类中的getter / setter属性,并且格式化在getset中进行,因此更难用原始值进行力变化检测。规避该困难的一种方法是在组件中定义一个configRendition getter / setter属性,然后将该属性分配给ngModel

<input #amount type="text" placeholder="xxx" [(ngModel)]="configRendition">

然后我们可以以这样的方式实现configRendition:在实际设置ChangeDetectorRef.detectChanges()之前先用原始值调用config.Rendition

private rawRendition: string;

get configRendition() {
  if (this.rawRendition) {
    return this.rawRendition;
  } else {
    return this.config ? this.config.rendition : null;
  }
}
set configRendition(value) {
  this.rawRendition = value;
  this.detector.detectChanges();
  if (this.config) {
    this.config.rendition = value;
  }
  this.rawRendition = null;
}

有关演示,请参见this stackblitz