介绍
Angular 的 @angular/forms 包带有一个 Validators 类,它支持有用的内置验证器,如 required、minLength、maxLength 和 [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 步 – 使用自定义验证器
接下来,创建一个包含 userName 和 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
并在您的网络浏览器中打开它。 您可以与 userName 和 websiteUrl 的字段进行交互。 确保 ValidateUrl 的自定义验证器按预期工作,其值应满足 https 和 .io 的条件:https://example.io。
结论
在本文中,您为 Angular 应用程序中的响应式表单创建了一个可重用的自定义验证器。
有关模板驱动表单和响应式表单中的自定义验证器的示例,请参阅 Angular 中的自定义表单验证。
如果您想了解有关 Angular 的更多信息,请查看 我们的 Angular 主题页面 以获取练习和编程项目。