在 Angular 中构建自定义验证器

发布日期:2026-07-10 00:29:03   来源 : 杭州电子商务研究院    浏览量 :13
杭州电子商务研究院 发布日期:2026-07-10 00:29:03  
13

介绍

大多数 Web、桌面和移动应用程序都包含各种表单,其中包含用于收集用户输入的字段。但在将值提交到服务器之前,我们必须对其进行验证。

在提交操作之前验证表单值是一项至关重要的任务,因为大多数应用程序都包含表单,因此用户可能会输入错误的值或黑客可能会试图窃取我们宝贵的数据。

验证者的形式

Angular 支持两种主要形式:

  • 模板驱动的表单
  • 响应式表单

Angular 表单是标准表单,但可能有附加字段,如输入框、复选框、选择等等。

表单中的每个字段都可以充当FormControl,返回有关该单个字段的完整信息,包括表单是否有效、实际字段值以及其他信息。

通过组合所有的表单控件,我们可以得到一个FormGroup,并且要求 Angular 中的每个表单都有一个FormGroup

这是我们可以用来创建表单、表单控件和表单组的两种表单方法,除此之外,我们还应该进行表单验证,以便在将值发送到服务器之前验证我们的表单。

Angular 中的自定义验证器

为了验证不同的表单字段,我们应该有一些业务逻辑,以便能够将有效值发送到服务器。

Angular 支持两种类型的表单验证器:内置验证器和自定义验证器。让我们来看看 Angular 中内置的表单验证器列表。

  • 分钟
  • 最大限度
  • 最小长度
  • 最大长度
  • 必需的
  • 撰写
  • 图案

除了这些内置验证器之外,还支持其他验证器,如果我们有验证表单中任何字段的特定要求,我们还可以创建自定义表单验证器。

创建自定义表单验证器

我们知道,有时内置验证器可能无法满足我们的验证要求,因此我们可能需要编写自定义验证逻辑来​​创建自定义表单验证器。

自定义验证器从FormControl中获取值,其中每个输入都充当FormControl。因此,让我们创建一个带有验证器函数的表单。

创建一个名为customvalidator.validator.ts的新文件并粘贴以下函数。

      import { FormGroup, AbstractControl } from "@angular/forms";

// To validate password and confirm password
export function ComparePassword(
  controlName: string,
  matchingControlName: string
) {
  return (formGroup: FormGroup) => {
    const control = formGroup.controls[controlName];
    const matchingControl = formGroup.controls[matchingControlName];

    if (matchingControl.errors && !matchingControl.errors.mustMatch) {
      return;
    }

    if (control.value !== matchingControl.value) {
      matchingControl.setErrors({ mustMatch: true });
    } else {
      matchingControl.setErrors(null);
    }
  };
}
    

这是我们简单的自定义验证器函数,它接受控件名称以及matchingControlName,它基本上比较了我们的示例中的两个不同字段。

下一步是使用该自定义验证器函数进入我们的组件,使用自定义表单验证器名称来初始化表单。

创建一个名为myform的新组件,打开myform.component.ts,并粘贴以下源代码。

      import { Component, OnInit } from "@angular/core";
import {
  FormBuilder,
  FormGroup,
  Validators,
  AbstractControl
} from "@angular/forms";
import {
  ComparePassword,
} from "../customvalidator/customvalidator.validator";

@Component({
  selector: "app-myform",
  templateUrl: "./myform.component.html",
  styleUrls: ["./myform.component.css"]
})
export class MyformComponent implements OnInit {
  registerForm: FormGroup;
  submitted = false;

  constructor(private formBuilder: FormBuilder) {}

  ngOnInit() {
    this.registerForm = this.formBuilder.group(
      {
        firstName: ["", [Validators.required]],
        lastName: ["", [Validators.required]],
        email: ["", [Validators.required, Validators.email]],
        password: ["", [Validators.required, Validators.minLength(6)]],
        confirmPassword: ["", Validators.required]
      },
      {
        // Used custom form validator name
        validator: ComparePassword("password", "confirmPassword")
      }
    );
  }

  // Getter function in order to get form controls value
  get f() {
    return this.registerForm.controls;
  }

  onSubmit() {
    this.submitted = true;

    // Returns false if form is invalid
    if (this.registerForm.invalid) {
      return;
    }

    console.log("Form Values" + JSON.stringify(this.registerForm.value));
  }
}
    

让我解释一下我们在这个组件中做了什么。

  • 我们已经使用FormBuilder初始化了表单,并使用FormBuilder组合了所有表单控件
  • 除了每个表单控件外,我们还使用了内置验证器,包括requiredemailminlength
  • 除了这些内置验证器之外,我们还使用了一个附加验证器ComparePassword,它接受密码、确认密码并根据函数执行返回结果。

这就是我们开发自定义表单验证器的方式。让我们为名字和姓氏字段实现另外两个自定义表单验证器。

      // To validate first name
export function ValidateFirstName(control: AbstractControl) {
  if (!control.value.startsWith("@")) {
    return { validFname: true };
  }
  return null;
}
    

在此函数中,我们将使用AbstractControl获得完整的表单控制,它是FormControlFormGroupFormArray的基类

使用该函数,我们验证用作名字的字符串是否应以@运算符开头;否则,我们将返回 null 作为结果。

      // To validate last name
export function ValidateLastName(control: AbstractControl) {
  if (control.value.length <= 3) {
    return { validLname: true };
  }
  return null;
}
    

这是另一个自定义表单验证器,它接受姓氏字符串并验证姓氏长度应超过三个字符。

到目前为止,我们已经创建了三种不同的自定义表单验证器:

  • 比较密码
  • 验证名字
  • 验证姓氏

在转到模板部分之前,我们需要将表单组源代码修改为组件,如下所示。

      ngOnInit() {
    this.registerForm = this.formBuilder.group(
      {
        firstName: ["", [Validators.required, ValidateFirstName]],
        lastName: ["", [Validators.required, ValidateLastName]],
        email: ["", [Validators.required, Validators.email]],
        password: ["", [Validators.required, Validators.minLength(6)]],
        confirmPassword: ["", Validators.required]
      },
      {
        // Used custom form validator name
        validator: ComparePassword("password", "confirmPassword")
      }
    );
}
    

现在我们完成了自定义表单验证器函数。下一步是将可视化表单创建到应用模板中。

打开myform.component.html并粘贴以下代码行。

      <form [formGroup]="registerForm" (ngSubmit)="onSubmit()">
	<table>
		<tr>
			<td></td>
		</tr>
		<tr>
			<td>First Name :</td>
			<td>
				<input type="text" formControlName="firstName" class="form-control" [ngClass]="{ 'is-invalid': submitted && f.firstName.errors }" />
				<div *ngIf="submitted && f.firstName.errors" class="invalid-feedback">
					<div *ngIf="f.firstName.errors.required">First Name is required</div>
				</div>
				<div *ngIf="registerForm.get('firstName').errors &&
      registerForm.get('firstName').dirty &&
      registerForm.get('firstName').errors.validFname">
					First name should start with @
				</div>
			</td>
		</tr>
		<tr>
			<td>Last Name :</td>
			<td>
				<input type="text" formControlName="lastName" class="form-control" [ngClass]="{ 'is-invalid': submitted && f.lastName.errors }" />
				<div *ngIf="submitted && f.lastName.errors" class="invalid-feedback">
					<div *ngIf="f.lastName.errors.required">Last Name is required</div>
				</div>
				<div *ngIf="registerForm.get('lastName').errors &&
      registerForm.get('lastName').dirty &&
      registerForm.get('lastName').errors.validLname">
					Last name should be > 3
				</div>
			</td>
		</tr>
		<tr>
			<td>Email :</td>
			<td>
				<input type="text" formControlName="email" class="form-control" [ngClass]="{ 'is-invalid': submitted && f.email.errors }" />
				<div *ngIf="submitted && f.email.errors" class="invalid-feedback">
					<div *ngIf="f.email.errors.required">Email is required</div>
					<div *ngIf="f.email.errors.email">Email must be a valid email address</div>
				</div>
			</td>
		</tr>
		<tr>
			<td>Password :</td>
			<td>
				<input type="password" formControlName="password" class="form-control" [ngClass]="{ 'is-invalid': submitted && f.password.errors }" />
				<div *ngIf="submitted && f.password.errors" class="invalid-feedback">
					<div *ngIf="f.password.errors.required">Password is required</div>
					<div *ngIf="f.password.errors.minlength">Password must be > 6 character long</div>
				</div>
			</td>
		</tr>
		<tr>
			<td>Confirm Password :</td>
			<td>
				<input type="password" formControlName="confirmPassword" class="form-control" [ngClass]="{ 'is-invalid': submitted && f.confirmPassword.errors }" />
				<div *ngIf="submitted && f.confirmPassword.errors" class="invalid-feedback">
					<div *ngIf="f.confirmPassword.errors.required">Confirm Password is required</div>
					<div *ngIf="f.confirmPassword.errors.mustMatch">Password should be same as Confirm password</div>
				</div>
			</td>
		</tr>
		<tr>
			<td>
				<button class="btn btn-primary">Register</button>
			</td>
		</tr>
	</table>
</form>
    

乍一看,它看起来很大,但别担心——我们将简要地看一下每个控件。

最重要的部分是表单标签,它表示这是一个表单,以及我们在组件中初始化的附加属性,例如formGroup 。

除了表单之外,我们还为它附加了一个名为ngSubmit的操作。这意味着一旦表单得到验证并提交,onSubmit函数就会在组件中触发。

在表单中,我们有不同的输入控件,以及附加的div<

以上内容来自杭州电子商务研究院推送
关注
关于我们
热门推荐
合作伙伴
免责声明:本站部分资讯来源于网络,如有侵权请及时联系客服,我们将尽快处理
Copyright © 2025-2027 ToB产业网址导航 公安备案 浙公网安备33010602013138号 浙ICP备16025413号-9
支持 反馈 关注 数据