Angular NgForm:重置准确的表单字段值不会使其有效

Angular NgForm: reset exact form filed value does not make it valid

我在组件模板上有一个表单:

<form (ngSubmit)="submitLogin(loginForm)" #loginForm="ngForm">
  <mat-input-container>
    <input matInput [placeholder]="'User Name'" ngModel name="username" autofocus required>
  </mat-input-container>
  <br>
  <mat-input-container>
    <input matInput [placeholder]="'Password'" ngModel type="password" name="password" required>
  </mat-input-container>
  <br>
  <button [disabled]="loginForm.invalid" mat-raised-button type="submit">
    Login
  </button>
</form>

这是我的组件的提交处理程序:

public submitLogin(loginForm: NgForm) {
  return this.authService.login(loginForm.value)
    .subscribe(
      res => this.router.navigate(['/customers']),
      error => loginForm.controls.password.reset() // this place!
    );
}

我明白了,登录错误(传递一些随机值)有效

问题。我怎样才能重置表单上的确切 fileld 并使其真正原始且未受影响?所以它应该是有效的,而不用在 UI.

上用红色 "invalid" 边框标记它

loginForm.controls.password.reset() 之后我看到 loginForm.controls.password.touchedfalse 并且 loginForm.controls.password.pristinetrue ,但我还看到 loginForm.controls.password.status 是“INVALID”。如果我破解它并直接将“VALID”值分配给status属性,红色的无效边框就会消失,但它会打破失去焦点的失效,以防万一我专注于那个文件,然后没有任何输入就离开了。应该有一种合法的方法来重置表单归档并同时使其有效。

您可以利用 markAs 现有功能

像这样

this.loginForm.controls.password.reset()
this.loginForm.controls.password.markAsPristine()
this.loginForm.controls.password.markAsUntouched()
this.loginForm.controls.password.updateValueAndValidity()

这些是实际的 API 功能,适用于当您想要强制执行特定状态并且不想完全依赖 Angular 决定字段状态

检查here如何更好地使用updateValueAndValidity方法

这似乎是一个已知问题。根据this错误状态计算如下:

isInvalid && (isTouched || isSubmitted)

因此,当您提交表单时,isSubmitted 标志设置为 true,因此条件满足并且您的字段显示为红色。有一些解决方法,如果你要重置整个表单,你可以使用 resetForm 代替,但在这里你只想重置一个字段,所以......

有个suggestion to use ErrorStateMatcher:

<input matInput 
   [placeholder]="'Password'" 
   ngModel type="password" 
   name="password" required 
   [errorStateMatcher]="matcher">

错误状态匹配器:

export class MyErrorStateMatcher implements ErrorStateMatcher {
  isErrorState(control: FormControl | null, form: FormGroupDirective | NgForm | null): boolean {
    // show errors when touched and invalid
    return (control.invalid && control.touched);
  }
}

并在您的 TS 中声明一个 ErrorStateMatcher:

matcher = new MyErrorStateMatcher();

似乎有效:StackBlitz