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

来自菜鸟教程
跳转至:导航、​搜索

介绍

Angular 的 @angular/forms 包带有一个 Validators 类,它支持有用的内置验证器,如 requiredminLengthmaxLength 和 [X140X ]。 但是,可能存在需要更复杂或自定义规则进行验证的表单字段。 在这些情况下,您可以使用自定义验证器。

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

在本教程中,您将使用可重用的自定义验证器构造一个反应式表单,以检查 URL 是否满足特定条件。

先决条件

要完成本教程,您需要:

  • Node.js 安装在本地,您可以按照【X57X】如何安装Node.js 并创建本地开发环境【X126X】进行。
  • 熟悉 设置 Angular 项目

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

第 1 步 - 设置项目

就本教程而言,您将从使用 @angular/cli 生成的默认 Angular 项目构建。

npx @angular/cli new angular-reactive-forms-custom-validtor-example --style=css --routing=false --skip-tests

这将配置一个新的 Angular 项目,其样式设置为“CSS”(与“Sass”、“Less”或“Stylus”相对)、无路由和跳过测试。

导航到新创建的项目目录:

cd angular-reactive-forms-custom-validator-example

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

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

src/app/app.module.ts

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 目录:

mkdir src/shared

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

src/shared/url.validator.ts

import { AbstractControl } from '@angular/forms';

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

此代码使用 Notice AbstractControl 类,它是 FormControls、FormGroups 和 FormArrays 的基类。 这允许访问 FormControl 的值。

此代码将检查值 startsWith 是否为 https 的字符串。 它还将检查值 includes 是否为 .io 的字符串。

如果验证失败,它将返回一个对象,其键为错误名称 invalidUrl,值为 true

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

此时,您的自定义验证器就可以使用了。

第 3 步 – 使用自定义验证器

接下来,创建一个包含 userNamewebsiteUrl 的表单。

打开app.component.ts,将内容替换为以下代码行:

src/app/app.component.ts

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 验证器。

第 4 步 – 访问模板中的错误

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

打开app.component.html,将内容替换为以下代码行:

src/app/app.component.html

<form [formGroup]="myForm" ngSubmit)="saveForm(myForm)">
  <div>
    <label>
      Username:
      <input formControlName="userName" placeholder="Your username">
    </label>
    <div *ngIf="(
                 myForm.get('userName').dirty ||
                 myForm.get('userName').touched
                ) &&
                myForm.get('userName').invalid"
    >
      Please provide your username.
    </div>
  </div>
  <div>
    <label>
      Website URL:
      <input formControlName="websiteUrl" placeholder="Your website">
    </label>
    <div
      *ngIf="(
              myForm.get('websiteUrl').dirty ||
              myForm.get('websiteUrl').touched
             ) &&
             myForm.get('websiteUrl').invalid"
      >
      Only URLs served over HTTPS and from the .io top-level domain are accepted.
    </div>
  </div>
</form>

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

npm start

并在您的网络浏览器中打开它。 您可以与 userNamewebsiteUrl 的字段进行交互。 确保 ValidateUrl 的自定义验证器按预期工作,其值应满足 https.io 的条件:https://example.io

结论

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

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

如果您想了解有关 Angular 的更多信息,请查看 我们的 Angular 主题页面 以获取练习和编程项目。