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.touched
是 false 并且 loginForm.controls.password.pristine
是 true ,但我还看到 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
我在组件模板上有一个表单:
<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.touched
是 false 并且 loginForm.controls.password.pristine
是 true ,但我还看到 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