如何防止 NgModel 设置无效的表单控件值?

How can I prevent NgModel from setting invalid form control values?

如何防止 NgModel 设置无效的 template-driven 表单控件值?我验证了 NgModel 在双向绑定到模型实例时会设置无效值。我知道我可以创建模型实例的副本,但我可能会遇到 save/revert 方法不合适的情况。

https://stackblitz.com/edit/angular-gcu9mz

@Component({
  selector: 'my-app',
  template: `
    Enter an invalid value (less than 14 characters).
    <br><br>
    <label for="input">Input:</label>
    <input #input="ngModel" type="text" minlength="14" [(ngModel)]="value" 
      placeholder="Enter an invalid value">
    Valid: {{input.valid}}
    <br>
    Model value: {{value}}
`
})
export class AppComponent  {
  value = 'Invalid value';
}

我发现了许多关于 AngularJS 的相关问题,其中据说 ngModelOptions 支持更改默认行为的 allowInvalid 配置。但是,Angular 的 NgModel 似乎不支持。

Don't record invalid values with ng-model

How to prevent model to be invalid?

我对 discussion 关于接受、显示或设置无效值是否是好的做法以及模型是否应该 "source of truth" 不感兴趣,因为我的要求始终取决于应用程序和用例。

您可以使用 getter 来包装您的验证逻辑。像这样:

@Component({
 selector: 'my-app',
 template: `
   Enter an invalid value (less than 14 characters).
   <br><br>
   <label for="input">Input:</label>
   <input #input="ngModel" type="text" minlength="14" [(ngModel)]="modelValue" 
   placeholder="Enter an invalid value">
   Valid: {{input.valid}}
   <br>
   Model value: {{modelValue}}`
})

export class AppComponent  {
 get modelValue() {
   let value;

   // validation logic to ensure value is valid

   return value; // valid value
 }
}

set modelValue(value) {
  //set value logic
}

来自 docs

To add validation to a template-driven form, you add the same validation attributes as you would with native HTML form validation. Angular uses directives to match these attributes with validator functions in the framework.

在link中,关于最小长度说

The number of characters (code points) must not be less than the value of the attribute, if non-empty.

您可以使用

<input required minlength="14 ....>

扩展 , I chose to utilize getters and setters but not to duplicate the validation logic. I used the FormControl's 有效性状态以防止在模型上设置无效值。

https://stackblitz.com/edit/angular-5xkael

@Component({
  selector: 'my-app',
  template: `
    <label for="input">Input:</label>
    <input #input="ngModel" type="text" minlength="14" [(ngModel)]="value">
`
})
export class AppComponent  {
  @ViewChild('input', { static: true }) input: NgControl;

  // Allow an initial invalid value.
  private _value = 'Invalid value';
  get value() { return this._value; }

  set value(value: string) { if (this.input.valid) this._value = value; }
}