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

介绍

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

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

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

先决条件

要完成本教程,您需要:

本教程已通过 Node v15.2.1、npmv6.14.8、@angular/corev11.0.0 和@angular/formsv11.0.0 验证。

步骤 1 – 设置项目

出于本教程的目的,您将从使用@angular/cli.

  • 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 { }

此时,您应该拥有一个新的 Angular 项目ReactiveFormsModule

第 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;
}

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

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

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

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

此时,您的自定义验证器已准备好使用。

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

接下来,创建一个包含 auserName和 a的表单websiteUrl

打开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 主题页面以获取练习和编程项目。

觉得文章有用?

点个广告表达一下你的爱意吧 !😁