输入上的ngModelChange无限循环

时间:2019-12-12 13:52:03

标签: angular typescript angular7 infinite-loop angular-ngmodelchange

我有一个类似这样的html:

<ng-template [ngSwitchCase]="'textbox'">
    <input *ngIf="setting.type==='number'"
           [step]="setting.step"
           [formControlName]="formName"
           [id]="formName"
           [type]="setting.type"
           [placeholder]="setting.placeholder"
           [title]="setting.description"
           (ngModelChange)="onChange($event)">
</ng-template>

在控制器上,我具有onChange函数:

onChange(newValue: string) {
    if (newValue === undefined)
        return;

    this.form.get(this.formName).setValue(<any>parseFloat(newValue));
}

当我调试onChange func的调用时,我注意到它仍在调用,真的不知道为什么。我有一个无限循环。

我的角度包:

"@angular/animations": "8.2.7",
"@angular/cli": "8.3.5",
"@angular/common": "8.2.7",
"@angular/compiler": "8.2.7",
"@angular/core": "8.2.7",
"@angular/forms": "8.2.7",
"@angular/platform-browser": "8.2.7",
"@angular/platform-browser-dynamic": "8.2.7",
"@angular/router": "8.2.7",
"@babel/polyfill": "7.6.0",

您是否知道我的代码可能出了什么问题?

2 个答案:

答案 0 :(得分:1)

可能是因为在onChange函数中设置了输入值,该函数再次更改了输入值并再次调用onChange。这无限地持续着。

在需要时将其投射为数字,而不是将字符串解析为数字,然后将其设置为不需要的控件。

parseFloat(this.form.get(this.formName).value)

+this.form.get(this.formName).value

在这种情况下,您不需要在每次更改值时将其解析为数字,而是在需要时进行解析。

您可以使用上述任一行将输入更改为数字,但不要再次将其设置为同一控件。

onChange(newValue: string) {
    parseFloat(this.form.get(this.formName).value)
}

答案 1 :(得分:1)

ControlValueAccessor方法

参见this answer,了解类似问题。我知道这个问题并不完全相同,但是据我所知,这似乎是一个可靠的方法。答案不是使用ngModelChange事件,而是建议包装输入组件并实现自定义ControlValueAccessor-请参见documentation

这里是这种方法的StackBlitz example。但是,它的行为似乎与blur事件类似,因此与下面的方法相比,在这种情况下,ControlValueAccessor可能会过大。

模糊事件方法

另一种选择是在您的输入上使用blur事件。当用户离开控件时,您只需更新值(解析为float),而不是每次更改值都尝试更新。像这样:

HTML

<ng-template [ngSwitchCase]="'textbox'">
    <input *ngIf="setting.type==='number'"
           [step]="setting.step"
           [formControlName]="formName"
           [id]="formName"
           [type]="setting.type"
           [placeholder]="setting.placeholder"
           [title]="setting.description"
           (blur)="onBlur()">   <!-- this line -->
</ng-template>

组件TypeScript

onBlur() {
    const value = this.form.get(this.formName).value;
    this.form.get(this.formName).setValue(<any>parseFloat(value));
}

Example是我在StackBlitz上为blur方法创建的。