我想执行表单验证。如果该字段“脏”。
如果密码字段中没有任何内容,则会显示错误。
如果密码不匹配,也应该显示错误。
你能向我解释一下我的代码有什么问题吗?我已经创建了一个代码示例:
https://stackblitz.com/edit/stackblitz-starters-wtwfd8?file=src%2Fmain.ts
我使用 Angular 17 和 Angular Material。
我们可以使用
?.
打字稿安全运算符来防止访问属性时 html 中出现任何错误。注意事项:
mismatch
验证器进行验证,但是我们在确认密码表单字段处显示了错误消息,因此我们需要通知表单控件该元素处于错误状态,为此我们可以使用 errorStateMatcher
输入绑定来更新表单,这将显示错误!错误状态匹配器代码!
export class MyErrorStateMatcher implements ErrorStateMatcher {
isErrorState(
control: FormControl | null,
form: FormGroupDirective | NgForm | null
): boolean {
return !!(form?.errors?.['mismatch'] && form?.touched);
}
}
...
...
export class App {
name = 'Angular';
registerForm: FormGroup;
matcher = new MyErrorStateMatcher();
html
...
<input matInput formControlName="confirmPassword" type="password" [errorStateMatcher]="matcher">
...
@switch
代替 @if
,因为我们通常一次显示一个错误,所以如果我们使用 switch
请找到下面的完整代码和工作 stackblitz 以供参考!
完整代码:
import { Component } from '@angular/core';
import { bootstrapApplication } from '@angular/platform-browser';
import 'zone.js';
import {
AbstractControl,
FormControl,
FormGroup,
NgForm,
ReactiveFormsModule,
Validators,
FormGroupDirective,
} from '@angular/forms';
import { MatInputModule } from '@angular/material/input';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatCheckboxModule } from '@angular/material/checkbox';
import { MatButtonModule } from '@angular/material/button';
import { FormsModule } from '@angular/forms';
import { provideAnimationsAsync } from '@angular/platform-browser/animations/async';
import { CommonModule } from '@angular/common';
import { ErrorStateMatcher } from '@angular/material/core';
export class MyErrorStateMatcher implements ErrorStateMatcher {
isErrorState(
control: FormControl | null,
form: FormGroupDirective | NgForm | null
): boolean {
return !!(form?.errors?.['mismatch'] && form?.touched);
}
}
@Component({
selector: 'app-root',
standalone: true,
imports: [
ReactiveFormsModule,
MatInputModule,
MatFormFieldModule,
MatCheckboxModule,
MatButtonModule,
FormsModule,
CommonModule,
],
template: `
<form [formGroup]="registerForm">
<mat-form-field>
<mat-label>Password</mat-label>
<input matInput formControlName="password" type="password">
@if (registerForm?.get('password')?.touched) {
<mat-error>
@switch (true) {
@case (registerForm.get('password')?.hasError('required')) {
Password is required
}
@case (registerForm.get('password')?.hasError('minlength')) {
Password must be 6 characters in length
}
}
</mat-error>
}
</mat-form-field>
<mat-form-field>
<mat-label>Confirm Password</mat-label>
<input matInput formControlName="confirmPassword" type="password" [errorStateMatcher]="matcher">
@if (registerForm?.get('confirmPassword')?.touched) {
<mat-error>
@switch (true) {
@case (registerForm.get('confirmPassword')?.hasError('required')) {
Confirm Password is required
}
@case (registerForm.errors?.['mismatch']) {
Password does not match
}
}
</mat-error>
}
</mat-form-field>
<button mat-raised-button color="primary " type="submit" [disabled]="!registerForm.valid">Sign up</button>
</form>
`,
})
export class App {
name = 'Angular';
registerForm: FormGroup;
matcher = new MyErrorStateMatcher();
constructor() {
this.registerForm = new FormGroup(
{
password: new FormControl('', [
Validators.required,
Validators.minLength(6),
]),
confirmPassword: new FormControl('', [Validators.required]),
},
{ validators: this.passwordMatchValidator }
);
}
private passwordMatchValidator(control: AbstractControl) {
return control.get('password')?.value ===
control.get('confirmPassword')?.value
? null
: { mismatch: true };
}
}
bootstrapApplication(App, {
providers: [provideAnimationsAsync()],
});