我的html上有一个输入字段,我需要限制它的值。
我正在尝试这样做:
HTML:
<div *ngFor="let option of options">
<input type="text" [ngModel]="option.value" (change)="onChangeValue($event.target.value, option)">
</div>
打字稿:
onChangeValue(valueString: string, option: OptionViewModel) {
var value: number = parseInt(valueString);
// Check some conditions. Simplified code just for example
if (option.value != value && value > 5) {
value = 5;
}
option.value = value;
}
OptionViewModel:
export class OptionViewModel {
public optionId: number;
public description: string;
public pollId: number;
public value?: number;
}
我尝试使用双向绑定,但我的代码依赖于option.value的先前值,并且在进入函数之前使用双向绑定更改变量。
问题是,有时输入字段没有更新。 看起来我刚刚第一次工作时需要更改值,所以例如,如果输入6字段正确地更改为5,但是如果我添加0(使其为50),则它不会更正为5.
我对代码进行了重新编译,它正在运行该函数并更改option.value,甚至使用Augury来检查对象是否显示正确的值。
答案 0 :(得分:2)
您尝试更改ng模型双向绑定,就像那样
<div *ngFor="let option of options">
<input type="text" [(ngModel)]="option.value" #ctrl="ngModel"
(change)="onChangeValue($event.target.value, option)">
</div>
答案 1 :(得分:2)
在第二次编辑时,输入元素的内容未更新,因为Angular未检测到任何更改(option.value
为5,且仍为5)。以下是强制刷新元素的两种方法。
方法1 - 替换数组中的选项
您可以通过使用克隆副本替换数组中的选项来强制更新字段,如 this stackblitz :
中所示<div *ngFor="let option of options; let i=index">
<input [ngModel]="option.value" (change)="onChangeValue($event.target.value, i)" type="text" >
</div>
onChangeValue(valueString: string, index: number) {
var value: number = parseInt(valueString);
if (value > 5) {
value = 5;
}
this.options[index] = this.options[index].cloneWithValue(value);
}
export class OptionViewModel {
public optionId: number;
public description: string;
public pollId: number;
public value?: number;
public cloneWithValue(value: number): OptionViewModel {
let dest = new OptionViewModel();
dest.optionId = this.optionId;
dest.description = this.description;
dest.pollId = this.pollId;
dest.value = value;
return dest;
}
}
方法2 - 在trackBy函数中使用其他字段
另一种解决方案是向OptionViewModel
添加其他字段(例如lastModified
),并在trackBy
指令的ngFor
方法中使用它(请参阅{{ 3}}):
<div *ngFor="let option of options; trackBy: trackByFn">
<input [ngModel]="option.value" (change)="onChangeValue($event.target.value, option)" type="text">
</div>
onChangeValue(valueString: string, option: OptionViewModel) {
var value: number = parseInt(valueString);
if (value > 5) {
value = 5;
}
option.value = value;
option.lastModified = Date.now();
}
trackByFn(index: number, option: OptionViewModel) {
return `${index}___${option.lastModified}`;
}
export class OptionViewModel {
public optionId: number;
public description: string;
public pollId: number;
public value?: number;
public lastModified: number = 0;
}
答案 2 :(得分:0)
您也可以尝试创建一个简单的observable来为您检查信息。
import { Component, ViewChild, ElementRef, OnInit } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/fromEvent';
import 'rxjs/add/operator/map';
@Component({
selector: 'my-app',
template: `<input #inputName type="text" />`,
})
export class AppComponent implements OnInit {
value: string = '';
@ViewChild('inputName') inputName: ElementRef;
ngOnInit() {
const input = this.inputName.nativeElement as HTMLInputElement;
Observable.fromEvent(input, 'input')
.map((evt: Event) => evt.target as HTMLInputElement)
.subscribe(target => target.value = Number(target.value) > 5 ? '5' : target.value);
}
}
答案 3 :(得分:0)
对我来说,最简单的解决方案是使用ChangeDetectorRef。更改检测树将收集所有视图并更新所有组件的值
在构造器中使ChangeDetectorRef的变量类型如下所示:-
constructor(private changeDet:ChangeDetectorRef) { }
现在只需在设置/更新值后调用 changeDet.detectChanges()
onChangeValue(valueString: string, option: OptionViewModel) {
var value: number = parseInt(valueString);
// Check some conditions. Simplified code just for example
if (option.value != value && value > 5) {
value = 5;
}
option.value = value;
this.changeDet.detectChanges();//Detects changes and updates value
}
答案 4 :(得分:0)
找到了一个更简单的解决方法。只需使用 (keyup) 而不是 (change)。
<input class="editable-field-input" type="number" value="editableFieldValue" [(ngModel)]="editableFieldValue" (keyup)="editableFieldValueChanged()" />
我没有将事件作为参数传递,因为我已经让 ngModel 更新了我的变量。
editableFieldValueChanged() {
if (this.editableFieldValue < -100) {
this.editableFieldValue = -100;
}
if (this.editableFieldValue > 100) {
this.editableFieldValue = 100;
}
}
TLDR 版本是,Angular 认为这与在下拉列表中一遍又一遍地选择相同的选项相同,因为以前的值和当前值是相同的,因此它找不到更新 DOM 元素的理由。
我相信这种方法有效,因为 (keyup) 与其他事件相比具有不同的执行顺序。我会把解释留给比我知识渊博的人。