如何在Angular表单中添加自定义验证器及密码匹配校验
问题描述
我有如下接口文件userslist.ts:
export interface Userslist { id: number; fname: string; lname: string; email: string; pas1: string; pas2: string; }
我使用该接口获取包含名字、姓氏、邮箱、密码及确认密码的表单数据,另外两个文件如下:
ucreate.component.ts:
import { Component, ViewChild, OnInit } from '@angular/core'; import { Router } from '@angular/router'; import { Userslist } from '../userslist'; import { UserslistService } from '../userslist.service'; @Component({ selector: 'app-ucreate', templateUrl: './ucreate.component.html', styleUrls: ['./ucreate.component.css'] }) export class UcreateComponent implements OnInit { userForm: Userslist = { id: 0, fname: '', lname: '', email: '', pas1: '', pas2: '', }; constructor(private userlistService: UserslistService, private router: Router) { } ngOnInit(): void { } create(){ this.userlistService.create(this.userForm) .subscribe({ next:(data) => { this.router.navigate(["/userslist/adminhome"]) }, error:(err) => { console.log(err); } }) } }
ucreate.component.html:
<div class="container"> <legend>Create Item</legend> <form> <div class="mb-3"> <label for="txtName" class="form-label">First Name</label> <input type="text" name="fname" [(ngModel)] = "userForm.fname" class="form-control" id="txtName" /> </div> <div class="mb-3"> <label for="txtName" class="form-label">Last Name</label> <input type="text" name="lname" [(ngModel)] = "userForm.lname" class="form-control" id="txtName" /> </div> <div class="mb-3"> <label for="txtName" class="form-label">e-mail</label> <input type="text" name="email" [(ngModel)] = "userForm.email" class="form-control" id="txtName" /> </div> <div class="mb-3"> <label for="txtName" class="form-label">Password</label> <input type="text" name="pas1" [(ngModel)] = "userForm.pas1" class="form-control" id="txtName" /> </div> <div class="mb-3"> <label for="txtName" class="form-label">Confirm Password</label> <input type="text" name="pas2" [(ngModel)] = "userForm.pas2" class="form-control" id="txtName" /> </div> <button type="button" (click)="create()" class="btn btn-primary">Create Account</button> </form> </div>
请问如何为上述输入字段添加自定义验证,以及如何显示两次输入的密码是否匹配?
解决方案
推荐使用Angular响应式表单实现验证,它比模板驱动表单更灵活,适合自定义验证场景。
步骤1:修改ucreate.component.ts文件
导入响应式表单模块,创建表单控件并添加内置验证器,同时自定义密码匹配验证函数:
import { Component, OnInit } from '@angular/core'; import { Router } from '@angular/router'; import { FormBuilder, FormGroup, Validators } from '@angular/forms'; import { Userslist } from '../userslist'; import { UserslistService } from '../userslist.service'; // 自定义密码匹配验证器 function passwordMatchValidator(form: FormGroup) { const password = form.get('pas1')?.value; const confirmPassword = form.get('pas2')?.value; return password === confirmPassword ? null : { mismatch: true }; } @Component({ selector: 'app-ucreate', templateUrl: './ucreate.component.html', styleUrls: ['./ucreate.component.css'] }) export class UcreateComponent implements OnInit { userForm: FormGroup; constructor( private userlistService: UserslistService, private router: Router, private fb: FormBuilder ) { // 初始化表单并添加验证规则 this.userForm = this.fb.group({ id: [0], fname: ['', [Validators.required, Validators.minLength(2)]], lname: ['', [Validators.required, Validators.minLength(2)]], email: ['', [Validators.required, Validators.email]], pas1: ['', [Validators.required, Validators.minLength(6)]], pas2: ['', Validators.required] }, { validators: passwordMatchValidator }); } ngOnInit(): void { } // 快捷获取表单控件,方便模板访问错误信息 get f() { return this.userForm.controls; } // 提交前先验证表单有效性 create(){ if (this.userForm.invalid) { this.userForm.markAllAsTouched(); return; } const userData: Userslist = this.userForm.value; this.userlistService.create(userData) .subscribe({ next:(data) => { this.router.navigate(["/userslist/adminhome"]) }, error:(err) => { console.log(err); } }) } }
步骤2:修改ucreate.component.html文件
更新模板绑定响应式表单,添加错误提示和密码匹配状态显示:
<div class="container"> <legend>Create Item</legend> <form [formGroup]="userForm"> <!-- 名字输入框 --> <div class="mb-3"> <label for="fname" class="form-label">First Name</label> <input type="text" formControlName="fname" class="form-control" id="fname" [ngClass]="{ 'is-invalid': f.fname.touched && f.fname.invalid }" /> <div *ngIf="f.fname.touched && f.fname.invalid" class="invalid-feedback"> <div *ngIf="f.fname.errors?.['required']">名字不能为空</div> <div *ngIf="f.fname.errors?.['minlength']">名字长度不能少于2位</div> </div> </div> <!-- 姓氏输入框 --> <div class="mb-3"> <label for="lname" class="form-label">Last Name</label> <input type="text" formControlName="lname" class="form-control" id="lname" [ngClass]="{ 'is-invalid': f.lname.touched && f.lname.invalid }" /> <div *ngIf="f.lname.touched && f.lname.invalid" class="invalid-feedback"> <div *ngIf="f.lname.errors?.['required']">姓氏不能为空</div> <div *ngIf="f.lname.errors?.['minlength']">姓氏长度不能少于2位</div> </div> </div> <!-- 邮箱输入框 --> <div class="mb-3"> <label for="email" class="form-label">e-mail</label> <input type="email" formControlName="email" class="form-control" id="email" [ngClass]="{ 'is-invalid': f.email.touched && f.email.invalid }" /> <div *ngIf="f.email.touched && f.email.invalid" class="invalid-feedback"> <div *ngIf="f.email.errors?.['required']">邮箱不能为空</div> <div *ngIf="f.email.errors?.['email']">请输入有效的邮箱格式</div> </div> </div> <!-- 密码输入框 --> <div class="mb-3"> <label for="pas1" class="form-label">Password</label> <input type="password" formControlName="pas1" class="form-control" id="pas1" [ngClass]="{ 'is-invalid': f.pas1.touched && f.pas1.invalid }" /> <div *ngIf="f.pas1.touched && f.pas1.invalid" class="invalid-feedback"> <div *ngIf="f.pas1.errors?.['required']">密码不能为空</div> <div *ngIf="f.pas1.errors?.['minlength']">密码长度不能少于6位</div> </div> </div> <!-- 确认密码输入框 --> <div class="mb-3"> <label for="pas2" class="form-label">Confirm Password</label> <input type="password" formControlName="pas2" class="form-control" id="pas2" [ngClass]="{ 'is-invalid': (f.pas2.touched && f.pas2.invalid) || userForm.hasError('mismatch') }" /> <div *ngIf="f.pas2.touched && f.pas2.invalid" class="invalid-feedback"> <div *ngIf="f.pas2.errors?.['required']">请确认密码</div> </div> <div *ngIf="userForm.hasError('mismatch') && f.pas2.touched" class="text-danger small"> 两次输入的密码不匹配 </div> </div> <button type="button" (click)="create()" class="btn btn-primary" [disabled]="userForm.invalid" >Create Account</button> </form> </div>
关键说明
- 响应式表单优势:通过
FormBuilder集中管理验证规则,逻辑清晰易维护。 - 内置验证器:使用
Validators.required(必填)、Validators.minLength(最小长度)、Validators.email(邮箱格式)等内置规则。 - 自定义密码验证:通过全局表单验证器对比密码与确认密码的值,返回验证结果。
- 错误提示:用
[ngClass]给无效控件添加样式,通过*ngIf判断控件状态和错误类型,显示对应提示。 - 提交拦截:提交前检查表单有效性,无效时标记所有控件为已触碰并终止提交。
内容的提问来源于stack exchange,提问作者AnkaDel
相关产品推荐
相关产品推荐

