角度表单不会验证您在单击之前未离开字段



我有一个有验证的有角度的表单。如果你在尝试提交表单之前点击框外,表单会很好地工作。否则,如果你点击回车键,或者在离开所有框之前点击提交按钮,它第一次什么都不会做,因为它还没有看到表单有效。不过,在下一次尝试时,它会提交。

我不确定什么能治好这个问题。register方法检查表单是否有效,但在单击按钮时,验证尚未完成,因为上一次输入框数据时onblur事件尚未完成。由于onblur活动只需单击按钮即可完成,因此可能有一种方法可以伪造onblur,或者至少在提交表单之前等待它?

无论如何,我不确定是否需要这个问题的代码,但我会添加我认为最相关的代码。

表单html:

<mat-card>
<mat-card-title>Register</mat-card-title>
<mat-card-content>
<form [formGroup]="form" (ngSubmit)="register(form.value)">
<p>
<mat-form-field>
<input type="text" matInput placeholder="Username" formControlName="username">
<mat-error *ngIf="checkError('username', 'required')">Username is required</mat-error>
<mat-error *ngIf="checkError('username', 'existingUser')">Username is already taken</mat-error>
</mat-form-field>
</p>
<p>
<mat-form-field>
<input type="password" matInput placeholder="Password" formControlName="password">
<mat-error *ngIf="checkError('password', 'required')">Password is required</mat-error>
</mat-form-field>
</p>
<p>
<mat-form-field>
<input type="password" matInput placeholder="Retype Password" formControlName="re_password">
<mat-error *ngIf="checkError('re_password', 'required')">Retype Password Required</mat-error>
<mat-error *ngIf="checkError('re_password', 'confirmedValidator')">Passwords must match</mat-error>
</mat-form-field>
</p>
<p>
<mat-form-field>
<input type="text" matInput placeholder="First Name" formControlName="first_name">
<mat-error *ngIf="checkError('first_name', 'required')">First name is required</mat-error>
</mat-form-field>
</p>
<p>
<mat-form-field>
<input type="text" matInput placeholder="Last Name" formControlName="last_name">
<mat-error *ngIf="checkError('last_name', 'required')">Last name is required</mat-error>
</mat-form-field>
</p>
<p>
<mat-form-field>
<input type="text" matInput placeholder="Email" formControlName="email">
<mat-error *ngIf="checkError('email', 'required')">Email is required</mat-error>
<mat-error *ngIf="checkError('email', 'email')">Invalid email</mat-error>
<mat-error *ngIf="checkError('email', 'existingEmail')">User with that email already exists</mat-error>
</mat-form-field>
</p>
<p *ngIf="errors" class="error">
{{errors}}
</p>
<div class="button">
<button type="submit" mat-button>Register</button>
</div>

</form>
</mat-card-content>
</mat-card>

表单组:

this.form = this.fb.group({
username: new FormControl('', {
validators: [Validators.required],
asyncValidators: [this.userValidator.existingUserValidator()],
updateOn: 'blur',
}),
password: new FormControl('', [
Validators.required,
Validators.minLength(8),
],
),
re_password: new FormControl('',
Validators.required,
),
first_name: new FormControl('',
Validators.required,
),
last_name: new FormControl('',
Validators.required,
),
email: new FormControl('', {
validators: [
Validators.required,
Validators.email,
],
asyncValidators: [this.emailValidator.existingEmailValidator()],
updateOn: 'blur',
}),
}, {
validators: MatchValidator('password', 're_password'),
});

register方法:

register(values): void {
if (this.form.valid) {
this.userService.register(values);
}
}

编辑:为了帮助有类似但不相关问题的人意识到他们的问题可能是不相关的,此问题是由提交前表单字段的异步验证引起的。我认为这只是因为使用的最后一个字段有一个验证器。

它会正确验证。材质元素只是在元素变为触摸(并且在第一次模糊后变为触摸(之前不会显示错误。从用户体验的角度来看,这被认为是一个很好的做法,因为当你要求用户填写你的表格时,你应该不那么无礼。但如果你仍然不喜欢这种行为,那么可以随意重写默认的ErrorStateMatcher

export class MyErrorStateMatcher implements ErrorStateMatcher {
isErrorState(control, form) {
return control && control.invalid; // will show error in every case when control is invalid. i.e. field will be red from the very beginning.
}
}
export class MyComponent {
...
customMatcher = new MyErrorStateMatcher();
}
.....
<input matInput [errorStateMatcher]="customMatcher">

您正在强制表单使用updateOn:'blur',这意味着"在表单失去焦点之前不要验证输入字段"。

如果你不使用服务器端(异步(验证,你可以使用"默认"验证策略,即updateOn:'change',这样每次用户按下键时都会运行Validator。

还有第三种策略是updateOn:"submit":每个字段的验证程序在您点击"提交"之前不会运行。

我刚刚做了这个。

我想在用户甚至没有触摸表单并且仍然按下按钮时,在按钮点击时显示所需的错误(如果表单无效,不想禁用(

this.loginForm.markAllAsTouched();

这将所有元素设置为触摸&在HTML*ngIf中作为

<span *ngIf="loginForm.get('email')?.invalid && loginForm.get('email')?.touched" >
{{ loginForm.get('email')?.errors?.required ? 'Username Required ' : 'Invalid Username' }}
</span>

最新更新