首页 文章

输入未更新视图时对NgModel的更改

提问于
浏览
2

我的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检查对象显示正确的值 .

3 回答

  • 2

    在第二次编辑时,输入元素的内容未更新,因为Angular未检测到任何更改( option.value 为5,它仍为5) . 以下是强制刷新元素的两种方法 .


    Method 1 - Replace the option item in the array

    您可以通过使用克隆副本替换数组中的选项来强制更新字段,如 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;
      }
    }
    

    Method 2 - Use an additional field in the trackBy function

    另一种解决方案是在 OptionViewModel (例如 lastModified )中添加一个附加字段,并在 ngFor 指令的 trackBy 方法中使用它(参见this stackblitz):

    <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;
    }
    
  • 0

    嗨尝试改变ng模型双向绑定,就像那样

    <div *ngFor="let option of options">
            <input type="text" [(ngModel)]="option.value"  #ctrl="ngModel"
     (change)="onChangeValue($event.target.value, option)">
        </div>
    
  • 2

    您还可以尝试创建一个简单的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);
      }
    }
    

相关问题