Angular:如果字段以前具有默认值,则将空字符串设置为默认值不会正确更新绑定文本字段
Angular: Setting an emptied string to a default value does not update the bound text field properly if the field previously had the default value
如果我们尝试将其设置为空字符串,我将使用 SET 方法将我的绑定值设置为 'DEFAULT'。绑定的文本输入在每种情况下都能正常运行,除非文本字段已经显示 'DEFAULT' 并且我“select 全部 + 删除”该值。绑定值立即正确设置回 'DEFAULT',但输入字段仍为空。
这是一个显示问题的 stackblitz
https://stackblitz.com/edit/angular-a9j8tv?file=src%2Fapp%2Fapp.component.html
如果你有 'DEFAULT' 并且你 select 全部删除,你可以看到输入保持为空,但是绑定到相同值的跨度正确显示新的 re-set 'DEFAULT' 值。
为什么会这样?
有解决办法吗?
问题来自 ngModel
。由于 ''
值操纵到 DEFAULT
,这是由 ngModel
触发的最新值,ngModel
没有实现值更改以触发新值更改事件。
如何解决;
在比较之前,我已经将变化的值直接赋给了setter
中的变量。然后将最小超时设置为 ngModel
可以更新其现有值。
然后当我比较新值并在 ''
的情况下将其更改回 DEFAULT
时,ngModel
实现值更改并触发新值更改事件。这会更新两个表示。
固有错误
ngModel
directive uses @Input
and @Output
获取值并发出更改事件。因此,使用默认更改检测策略将 setter 或 getter 之类的函数绑定到 [ngModel]
之类的指令将触发每个更改检测的函数。
要重现此错误,请在 getter 中插入 console.log
,键入一些值并在 <input>
中继续按退格键,然后松开。您可以看到 console.log
消息不断打印。
错误复制:Stackblitz
为什么 'DEFAULT' 没有插入 Ctrl+a+Backspace
如前所述,ngModel
指令使用 @Input
并且相应地 ngOnChanges()
hook to fetch any changes to the value from <input>
tag. One important thing to note is ngOnChanges()
不会 如果值没有被触发' t 改变了(1).
我们可以尝试将双向绑定 [(ngModel)]
拆分为 [ngModel]
输入和 (ngModelChange)
输出。
export class AppComponent {
public testString: string;
onChange(value: string) {
this.testString = value === '' ? 'DEFAULT' : value;
}
}
<input type="text" [ngModel]="testString" (ngModelChange)="onChange($event)" />
仍然容易出错:Stackblitz
这里Ctrl+a+Backspace除[=110=以外的任何字符串] 将按预期插入 'DEFAULT'。但是 Ctrl+a+Backspace 'DEFAULT' 会导致空 <input>
由于上面讨论的 ngOnChanges()
问题。
解决方案
实现预期行为的一种方法是不依赖ngModel
指令的ngOnChanges()
挂钩来设置值,而是我们自己手动完成.为此,我们可以在 <input>
中使用 Angular template reference variable 并将其发送到组件以进行进一步操作。
export class AppComponent {
public testString: string;
public onChange(value: string, inputElem: HTMLInputElement) {
this.testString = value === '' ? 'DEFAULT' : value;
inputElem.value = this.testString;
}
}
<input
type="text"
#myInput
ngModel
(ngModelChange)="onChange($event, myInput)"
/>
工作示例:Stackblitz
这里的#myInput
是模板引用变量。如果这感觉很老套,你需要知道使用 ngModel
来操纵 <input>
本身就叫做 template driven forms。直接操作模板引用是完全合法的。
综上所述,IMO 在需要此类输入操作的情况下,我建议您改用 Angular Reactive Forms。它提供了对输入更精细的控制。
(1) 如果 @Input
的 previousValue
和 currentValue
不会触发 ngOnChanges()
变量的 SimpleChange
对象没有改变。
如果我们尝试将其设置为空字符串,我将使用 SET 方法将我的绑定值设置为 'DEFAULT'。绑定的文本输入在每种情况下都能正常运行,除非文本字段已经显示 'DEFAULT' 并且我“select 全部 + 删除”该值。绑定值立即正确设置回 'DEFAULT',但输入字段仍为空。
这是一个显示问题的 stackblitz https://stackblitz.com/edit/angular-a9j8tv?file=src%2Fapp%2Fapp.component.html
如果你有 'DEFAULT' 并且你 select 全部删除,你可以看到输入保持为空,但是绑定到相同值的跨度正确显示新的 re-set 'DEFAULT' 值。
为什么会这样? 有解决办法吗?
问题来自 ngModel
。由于 ''
值操纵到 DEFAULT
,这是由 ngModel
触发的最新值,ngModel
没有实现值更改以触发新值更改事件。
如何解决;
在比较之前,我已经将变化的值直接赋给了setter
中的变量。然后将最小超时设置为 ngModel
可以更新其现有值。
然后当我比较新值并在 ''
的情况下将其更改回 DEFAULT
时,ngModel
实现值更改并触发新值更改事件。这会更新两个表示。
固有错误
ngModel
directive uses @Input
and @Output
获取值并发出更改事件。因此,使用默认更改检测策略将 setter 或 getter 之类的函数绑定到 [ngModel]
之类的指令将触发每个更改检测的函数。
要重现此错误,请在 getter 中插入 console.log
,键入一些值并在 <input>
中继续按退格键,然后松开。您可以看到 console.log
消息不断打印。
错误复制:Stackblitz
为什么 'DEFAULT' 没有插入 Ctrl+a+Backspace
如前所述,ngModel
指令使用 @Input
并且相应地 ngOnChanges()
hook to fetch any changes to the value from <input>
tag. One important thing to note is ngOnChanges()
不会 如果值没有被触发' t 改变了(1).
我们可以尝试将双向绑定 [(ngModel)]
拆分为 [ngModel]
输入和 (ngModelChange)
输出。
export class AppComponent {
public testString: string;
onChange(value: string) {
this.testString = value === '' ? 'DEFAULT' : value;
}
}
<input type="text" [ngModel]="testString" (ngModelChange)="onChange($event)" />
仍然容易出错:Stackblitz
这里Ctrl+a+Backspace除[=110=以外的任何字符串] 将按预期插入 'DEFAULT'。但是 Ctrl+a+Backspace 'DEFAULT' 会导致空 <input>
由于上面讨论的 ngOnChanges()
问题。
解决方案
实现预期行为的一种方法是不依赖ngModel
指令的ngOnChanges()
挂钩来设置值,而是我们自己手动完成.为此,我们可以在 <input>
中使用 Angular template reference variable 并将其发送到组件以进行进一步操作。
export class AppComponent {
public testString: string;
public onChange(value: string, inputElem: HTMLInputElement) {
this.testString = value === '' ? 'DEFAULT' : value;
inputElem.value = this.testString;
}
}
<input
type="text"
#myInput
ngModel
(ngModelChange)="onChange($event, myInput)"
/>
工作示例:Stackblitz
这里的#myInput
是模板引用变量。如果这感觉很老套,你需要知道使用 ngModel
来操纵 <input>
本身就叫做 template driven forms。直接操作模板引用是完全合法的。
综上所述,IMO 在需要此类输入操作的情况下,我建议您改用 Angular Reactive Forms。它提供了对输入更精细的控制。
(1) 如果 @Input
的 previousValue
和 currentValue
不会触发 ngOnChanges()
变量的 SimpleChange
对象没有改变。