我有一个组件可以对输入控件中的更改做出反应,并通过删除某些字符来对其重新格式化。设置完成后,备份字段中存储的值可能会更改或不会更改。在第一种情况下,一切正常,但是如果删除的字符映射到先前的值,则不会检测到任何更改,并且组件也不会更新。导致包含可移动字符的值停留在输入框中。
如何强制通过 [(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上的可播放演示。)
答案 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属性,并且格式化在get
和set
中进行,因此更难用原始值进行力变化检测。规避该困难的一种方法是在组件中定义一个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。