Yog*_*esh 4 angular2-ngmodel angular
我有一个输入字段,用户可以在其中输入事物的速率。
当用户输入值时,我希望将其四舍五入后再显示,然后将更新后的值存储在ts文件的后备模型中。
使用Angular管道不利于此,因为一个方向的管道和更新后的值不会反映在模型上。
因此,为了使其双向,我正在执行以下操作:
<input type="text" [ngModel]="model.rate" (ngModelChange)="model.rate=roundRate($event)" name="rate" />
Run Code Online (Sandbox Code Playgroud)
该roundDate功能看起来像这样
roundRate(value) {
return Math.round(value);
}
Run Code Online (Sandbox Code Playgroud)
现在,当我输入5.6、7.8、9.5等值时,它们都被四舍五入,显示并分别在模型上存储为6、8和10,这是预期的行为。
当我输入2.1、3.4、5.3等时,问题开始。在这种情况下,该roundRate函数被调用,并在四舍五入后返回值。但是屏幕上显示的值仍然是旧值(2.1、3.4、5.3)
我检查了inputChrome上的元素,发现该ng-reflect-model属性已更新为预期值(2、3、5)。
<input _ngcontent-c39="" name="rate" type="text" ng-reflect-name="rate" ng-reflect-model="5" class="ng-valid ng-dirty ng-touched">
Run Code Online (Sandbox Code Playgroud)
有人可以解释一下这里发生了什么吗,尽管ng-reflect-model属性已更新,但为什么屏幕仍显示旧值?
谢谢你的帮助!
与在细看开始ngModel指令API,你会看到,ngModel在@Input结合它接受一些价值作为model变量。在初始化ngModel控制时,它会FormControl隐式创建。
public readonly control: FormControl = new FormControl();
Run Code Online (Sandbox Code Playgroud)
更新model值的神奇之处在于ngOnChangeshook,通过这种方式,它可以将视图值与modelvalue 同步。如果仔细看一下ngOnChanges钩子,您会发现它会验证输入并也应用其他检查,然后严格检查ngModel值是否真的使用isPropertyUpdated方法更改了。
ngOnChanges -ngModel指令
ngOnChanges(changes: SimpleChanges) {
this._checkForErrors();
if (!this._registered) this._setUpControl();
if ('isDisabled' in changes) {
this._updateDisabled(changes);
}
if (isPropertyUpdated(changes, this.viewModel)) {
this._updateValue(this.model); // helps to update
this.viewModel = this.model;
}
}
private _updateValue(value: any): void {
resolvedPromise.then(() => {
// set value will set form control
this.control.setValue(value, {emitViewToModelChange: false});
});
}
Run Code Online (Sandbox Code Playgroud)
但是要使其实现,Angular应该在变更检测周期内识别出变更。由于我们没有更改模型,因此不会触发ngOnChanges钩子:
到目前为止,我所解释的是API部分。让我们回到这个问题。
在stackblitz中尝试以下代码片段,这是我们的期望。输入值更改时,应将该值设置为其10自身。
<input type="text"
[ngModel]="model.rate"
(ngModelChange)="model.rate = 10"
name="rate" />
Run Code Online (Sandbox Code Playgroud)
不幸的是,这种情况并没有发生,您将看到在初始输入任何数字时,它将把输入值更改为10,随后您将键入的任何内容将继续添加到数字输入中。啊,想知道为什么吗?
让我们再回到原始问题,
<input type="text"
[ngModel]="model.rate"
(ngModelChange)="model.rate=roundRate($event)"
name="rate" />
{{model.rate}}
Run Code Online (Sandbox Code Playgroud)
ngModel用作绑定的一种方式。预期的行为是,分配给的任何值model.rate都应反映在中input。让我们尝试输入1.1,您会看到它显示了我们的价值1.1。现在尝试输入1.2,结果为1.2 1。想知道为什么吗?但可以肯定的是model.rate绑定可以正确更新。类似地,检查4.6,4.8得到5个效果最佳。
让我们将其分解为上面的示例,当您尝试输入时会发生什么1.1。
1 => model.rate变成11. => model.rate停留11.1=> model.rate停留1最终当您键入1.1或1.2模型值保留1以来,我们便会Math.round重视。由于它不是更新model.rate值,因此您输入的任何内容都将被ngModel绑定忽略,并显示在input字段中。
检查4.6,是否4.8完美。为什么?明智地分解它
4 => model.rate变成44. => model.rate停留44.6=> model.rate 变成 5在此处输入4.6文本框时,Math.round值变为5。model.rate(ngModel)值的更改将导致input字段值的更新
现在再次开始阅读答案,最初说明的技术方面也将被清除。
注意:在阅读答案时,请按照摘录中提供的链接进行操作,这可能有助于您更准确地理解它。
为了使它起作用,您可以尝试在blur/ change上更新您的字段,而在该事件上,焦点会fields像这样Sid's answer。之所以奏效,是因为您将重点放在领域上一次更新了模型。
但是它只能工作一次。为了保持不断更新,我们可以采取一些措施:
this.model.rate = new String(Math.round(value));
Run Code Online (Sandbox Code Playgroud)
每当我们舍入我们的值时,这将导致一个新的对象引用。
为了更简洁的实现,只需使用(change) @Output属性 和[(ngModel)]。的实现roundRate将改变如下:
import { Component } from '@angular/core';
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
model = { rate: null };
roundRate() {
this.model.rate = Math.round(+this.model.rate);
}
}
Run Code Online (Sandbox Code Playgroud)
并在模板中:
<input type="text" [(ngModel)]="model.rate" (change)="roundRate()" name="rate" />
Run Code Online (Sandbox Code Playgroud)
PS:blur只有当您从输入字段中更改该值时,才会更新该值
这是一个StackBlitz 示例供您参考。
| 归档时间: |
|
| 查看次数: |
3786 次 |
| 最近记录: |