如何在 Angular 中为响应式表单创建自定义验证器

简介

Angular 的 @angular/forms 包提供了一个 Validators 类,支持诸如 requiredminLengthmaxLengthpattern 等有用的内置验证器。然而,可能存在需要更复杂或自定义规则进行验证的表单字段。在这种情况下,您可以使用自定义验证器。

在 Angular 中使用响应式表单时,您可以使用函数定义自定义验证器。如果验证器不需要被重复使用,它可以直接存在于组件文件中作为一个函数。否则,如果验证器需要在其他组件中重复使用,它可以存在于一个单独的文件中。

在本教程中,您将构建一个带有可重用自定义验证器的响应式表单,以检查 URL 是否符合特定条件。

先决条件

要完成本教程,您需要:

  • 在本地安装 Node.js,您可以按照《如何安装 Node.js 并创建本地开发环境》进行操作。
  • 一些关于设置 Angular 项目的基本知识。

本教程已经在 Node v15.2.1、npm v6.14.8、@angular/core v11.0.0 和 @angular/forms v11.0.0 下进行了验证。

步骤 1 -- 设置项目

为了本教程的目的,您将从使用 @angular/cli 生成的默认 Angular 项目开始构建。

command 复制代码
npx @angular/cli new angular-reactive-forms-custom-validtor-example --style=css --routing=false --skip-tests

这将配置一个新的 Angular 项目,其中样式设置为 "CSS"(而不是 "Sass"、"Less" 或 "Stylus"),没有路由,并且跳过了测试。

进入新创建的项目目录:

command 复制代码
cd angular-reactive-forms-custom-validator-example

为了使用响应式表单,您将使用 ReactiveFormsModule 而不是 FormsModule

在代码编辑器中打开 app.module.ts 并添加 ReactiveFormsModule

typescript 复制代码
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { ReactiveFormsModule } from '@angular/forms';

import { AppComponent } from './app.component';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    ReactiveFormsModule,
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

到此为止,您应该已经拥有一个带有 ReactiveFormsModule 的新 Angular 项目。

步骤 2 -- 构建自定义验证器

本教程的示例自定义验证器将接受一个 URL 字符串,并确保它以 https 协议开头并以 .io 顶级域名结尾。

首先,在您的终端中,创建一个 shared 目录:

command 复制代码
mkdir src/shared

然后,在这个新目录中,创建一个新的 url.validator.ts 文件。在代码编辑器中打开此文件并添加以下代码:

typescript 复制代码
import { AbstractControl } from '@angular/forms';

export function ValidateUrl(control: AbstractControl) {
  if (!control.value.startsWith('https') || !control.value.includes('.io')) {
    return { invalidUrl: true };
  }
  return null;
}

这段代码使用了 AbstractControl 类,它是 FormControlFormGroupFormArray 的基类。这允许访问 FormControl 的值。

这段代码将检查值是否以 https 字符串开头。它还将检查值是否包含 .io 字符串。

如果验证失败,它将返回一个带有错误名称 invalidUrl 和值 true 的对象。

否则,如果验证通过,它将返回 null

到此为止,您的自定义验证器已经准备就绪。

步骤 3 -- 使用自定义验证器

接下来,创建一个表单,其中包含 userNamewebsiteUrl

打开 app.component.ts 并用以下代码替换内容:

typescript 复制代码
import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';

import { ValidateUrl } from '../shared/url.validator';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
  myForm: FormGroup;

  constructor(private fb: FormBuilder) {}

  ngOnInit() {
    this.myForm = this.fb.group({
      userName: ['', Validators.required],
      websiteUrl: ['', [Validators.required, ValidateUrl]]
    });
  }

  saveForm(form: FormGroup) {
    console.log('Valid?', form.valid); // true or false
    console.log('Username', form.value.userName);
    console.log('Website URL', form.value.websiteUrl);
  }
}

在这段代码中,websiteUrl 表单控件同时使用了内置的 Validators.required 和自定义的 ValidateUrl 验证器。

第四步 -- 访问模板中的错误信息

与您的表单交互的用户需要了解哪些数值未通过验证。在组件模板中,您可以使用自定义验证器返回值中定义的键。

打开 app.component.html 并用以下代码替换内容:

html 复制代码
<form [formGroup]="myForm" (ngSubmit)="saveForm(myForm)">
  <div>
    <label>
      用户名:
      <input formControlName="userName" placeholder="您的用户名">
    </label>
    <div *ngIf="(
                 myForm.get('userName').dirty ||
                 myForm.get('userName').touched
                ) &&
                myForm.get('userName').invalid"
    >
      请提供您的用户名。
    </div>
  </div>
  <div>
    <label>
      网站 URL:
      <input formControlName="websiteUrl" placeholder="您的网站">
    </label>
    <div
      *ngIf="(
              myForm.get('websiteUrl').dirty ||
              myForm.get('websiteUrl').touched
             ) &&
             myForm.get('websiteUrl').invalid"
      >
      仅接受通过 HTTPS 提供且来自 .io 顶级域的 URL。
    </div>
  </div>
</form>

此时,您可以编译您的应用程序:

command 复制代码
npm start

然后在您的网络浏览器中打开它。您可以与 userNamewebsiteUrl 字段进行交互。确保您的 ValidateUrl 的自定义验证器对于应满足 https.io 条件的值(例如 https://example.io)能够正常工作。

结论

在本文中,您为 Angular 应用程序中的响应式表单创建了一个可重用的自定义验证器。

要了解模板驱动表单和响应式表单中自定义验证器的示例,请参阅 Angular 中的自定义表单验证。

如果您想了解更多关于 Angular 的知识,请查看我们的 Angular 主题页面,了解练习和编程项目。

相关推荐
Pedantic15 小时前
SwiftUI 手势层级(Gesture Hierarchy)详解
前端
飘尘16 小时前
前端转型全栈(Java后端)的快速上手指引
前端·后端·全栈
一颗烂土豆16 小时前
Meshopt 压缩深度解析,为什么它比 Draco 更快
前端·javascript·webgl
浏览器工程师17 小时前
AI Agent 接浏览器任务,先别让它一路点到底
前端·后端
starrysky81017 小时前
Hermes Agent 的 70+ 工具不是硬编码的:一套自注册的注册表引擎 [04]
angular.js
雨季mo浅忆17 小时前
VSCode自动格式化三要素
前端
爱勇宝18 小时前
深扒 Anthropic 1680 位工程师简历:应届生几乎没机会,AI 公司最缺的不是博士
前端·后端·程序员
kyriewen18 小时前
同事每天催我 Code Review,我写了个脚本让 AI 替我 review PR——现在他反过来催 AI 了
前端·javascript·ai编程
user205855615181320 小时前
Windows 项目安装时报 `node-sass` 错误,如何快速处理
前端