【问题标题】:Angular 2 keep input form value in bind with the model using getter and setterAngular 2使用getter和setter将输入表单值与模型绑定
【发布时间】:2017-08-08 19:56:40
【问题描述】:

我想使用 getter 和 setter 将输入值绑定到模型。通过这种方式,我可以在写入时防止和/或操纵输入的值。

例如,我想要输入框中的阻止数字。所以,如果写 'abc' 一切正常,那么如果我开始写一个数字,什么都不会发生(模型和输入的值)。问题是,使用下面的代码,我可以在输入框中写任何东西(但模型是正确的)。这意味着输入框的值并不能真正代表我的模型。

注意:除此问题之外的原因是我想使用我的模型来验证表单,例如防止特定字符。我不想使用响应式表单,因为我想将我的验证保存在我的模型而不是组件中。另外请注意,在实际场景中,我将有一个带有内部名称的 UserModel 类和带有验证的其他字段.

@Component({
  selector: 'my-app',
  template: `
    <div>
      <h2><input type="text" [(ngModel)]="name"> {{name}}</h2>
    </div>
  `,
})
export class App {
  _name:string = 'ss';
  constructor() {
  }

  // In real scenario those 2 methods are in a separate class UserModel
  get name() {
    return this._name;
  }

  set name() {
    if ((new RegExp(/^[a-zA-Z]*$/).test(val))) {
        this._name = val;
    }
  }
}

【问题讨论】:

  • 有什么问题?
  • 我更新了问题希望现在更清楚了。
  • 请提供一个关于你想要什么的具体例子。你不想要的东西并没有太大帮助;-) 所以如果this._name 持有价值abc 并且用户输入123 但你不想允许数字,那么究竟应该发生什么?
  • 没什么,输入值应该保持abc。 (我在问题中添加了一个更好的例子)

标签: angularjs angular data-binding getter-setter


【解决方案1】:

如果您在设置器中操作值,这可能会导致更改检测出现问题,因此ngModel 不会获取更改并且不会更新&lt;input&gt;

要解决你可以使用

export class App {

  _name:string = 'ss';

  constructor(private cdRef:ChangeDetectorRef) {}

  get name() {
    return this._name;
  }

  set name(value:String) {
    this._name = value + 'x';
    this.cdRef.detectChanges()
  }
}

如果您将值重置为之前的值,您可能需要先传递一个人为的不同值,否则更改检测不会检测到更改,甚至detectChanges() 也不会更新输入。

  set name(value:String) {
    var oldVal = this._name;
    this._name = null;
    this.cdRef.detectChanges()
    this._name = oldVal;
    this.cdRef.detectChanges()
  }

【讨论】:

  • 这行得通,但它真的很棘手。我不想在我的所有模型中都有 detectChanges
  • 我不知道更好的方法。
  • 根据我的测试,必须先按上述方法更改值。
【解决方案2】:

根据@Günter Zöchbauer 的回答,我做了一个解决方法。它不是确定的,可能更抽象,但现在还可以。

export class App implements OnInit {
    @Input() userModel: UserModel = null;
    public _vm;

    constructor(private _changeDetectionRef: ChangeDetectorRef) {
    }

    /**
     * Initalize view model, it's important to keep names specular
     */
    ngOnInit() {
        this._vm = {
            name: this.userModel.name,
            surname: this.userModel.surname,
        };
    }

    /**
     * Helper for avoid detectchanges inside the modal, and reduce boilerplate. We could also ad an interface/type of the possibile field value, ie type fieldT= 'name' | 'surname';
     * @param field
     * @param val
     */
    protected updateModel(field, val: string): void {
        this._vm[field] = null;
        this._changeDetectionRef.detectChanges();
        this.userModel[field] = val;
        this._vm[field] = this.userModel[field];
        this._changeDetectionRef.detectChanges();
    }
}

在用户模型中:

....

    public get name(): string {
        return this.name';
    }

    public set name(val: string) {
        if ((new RegExp(/^[a-zA-Z]*$/).test(val))) {
            this.name = val;
        }
    }

在模板中:

<input type="text"  name="userName"  [ngModel]="_vm.name" (ngModelChange)="updateModel('name', $event)">

【讨论】:

    【解决方案3】:

    您可以使用(ngModelChange)[ngModel] 在更改时测试模型的内容。

    正如您在此 Plunker 中看到的,如果模型无效,则模型不会更改。

    @Component({
      selector: 'my-app',
      template: `
        <div>
          <h2><input #input type="text" [ngModel]="name" (ngModelChange)='valid(input.value)'> {{name}}</h2>
        </div>
      `,
    })
    export class App {
      name:string = 'ss';
      constructor() {
      }
    
      valid(value){
        if(value){ //<--- Your test here
          this.name = value;
        }
      }
    
    }
    

    【讨论】:

      猜你喜欢
      • 2017-03-13
      • 2017-12-07
      • 1970-01-01
      • 2014-09-06
      • 1970-01-01
      • 2018-05-03
      • 2017-11-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多