【问题标题】:Forcing change detection when value bound to doesn't change当绑定到的值不变时强制进行更改检测
【发布时间】:2019-09-23 11:56:10
【问题描述】:

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

如何强制通过 [(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">

我尝试使用 markForCheck()detectChanges()onKeyUp 中执行检测更改,声明为 in docs。没有区别。

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

Blitzy 上的可播放演示。)

【问题讨论】:

  • 你能告诉我们在 stackblitz 中应该怎么做才能看到问题吗?
  • @ConnorsFan 对不起。如果单击重新排列,第三个框(带有 xxx)会接收输入。尝试输入 12345,您会看到格式为 12 345。如果您输入 12345m 并且没有任何反应,但如果您输入 12345m6,则开始进行过滤。在控制台中,我打印出支持字段的状态并 get rendition() 并且这些是正确的。只是输入看到绑定到的值还是和之前一样(虽然和盒子的内容不同)。然后,控件不会更新掉非数字。
  • 当我输入12345m 时,我在字段中看到12 345(在短暂看到m 之后)。这不正确吗?
  • @ConnorsFan 我汗流浃背,以前没有!显然,这是某种巫术......那,或者我混淆了两个叉子并顺便修复了另一个(我正在尝试自己的东西,所以我不太依赖)。我对巫术的投票是 80-20...谢谢伙计,非常抱歉在您尝试提供帮助时浪费了您的时间。我猜是我的错。
  • @ConnorsFan 当我们谈到这个主题时,我不妨问问那里短暂可见的角色。你能想办法摆脱它吗?或者让它如此简短以至于眼睛无法捕捉到它?我尝试了 onKeyDown 并使用了指令,但它并没有按照人们想要的方式工作。

标签: angular typescript data-binding


【解决方案1】:

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

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

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,在实际设置config.Rendition之前首先使用原始值调用ChangeDetectorRef.detectChanges()

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 以获取演示。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-09-27
    • 1970-01-01
    • 1970-01-01
    • 2013-04-26
    • 2018-01-14
    • 2012-12-06
    • 2013-06-09
    相关资源
    最近更新 更多