Angular 是一个流行的前端框架,Angular 应用通常需要表单,而表单需要验证,为了优化用户体验,我们需要在 Angular 应用中实现优雅的表单验证机制。这篇文章将介绍如何在 Angular 应用中实现优雅的表单验证,包括模板驱动和响应式表单检验的方法,以及使用自定义验证器和异步验证器的技巧。
模板驱动表单验证
在 Angular 应用中使用模板驱动表单,我们可以在模板中使用 Angular 表单指令来实现表单验证。Angular 表单指令包括以下几种:
ngModel:绑定输入框的值,同时可以给输入框添加验证器
ngForm:核心表单指令,管理一组 form controls 的状态、验证和值
ngControl:创建一个表单控件,可以直接访问其值、验证状态和发出变更事件
ngSubmit:监听表单提交事件
下面是一个示例代码,演示如何使用模板驱动表单验证:
-- -------------------- ---- ------- ----- ---------------- ------------------------------ ---- ------------------- ------ -------------------------------- ------ ----------- ------------- --------------- -------------------- -------- ------------- ---------------------------- -------------------- ---- ----------------------- -- --------------- -- ------------------ ------------ -------------- ---- --------------------------------- -------- -- --------- ------ ---- ---------------------------------- -------- ---- -- -- ----- - ---------- ----- ------ ------ ------ ---- ------------------- ------ -------------------------------- ------ --------------- ------------- --------------- -------------------- -------- ------------- ---------------------------- -------------------- ---- ----------------------- -- --------------- -- ------------------ ------------ -------------- ---- --------------------------------- -------- -- --------- ------ ---- ---------------------------------- -------- ---- -- -- ----- - ---------- ----- ------ ------ ------ ------- ------------- ---------- ------------ ------------------------------------------- -------
在上面的代码中,我们使用了 ngForm
指令来创建一个核心表单对象,同时使用 ngModel
指令来绑定输入框的值和验证状态。我们还使用了 #username
和 #password
模板变量来引用输入框,这样就可以在模板中访问它们的验证状态。使用 *ngIf
指令来根据验证状态显示错误消息,在提交表单时,我们检查表单是否有效(即无验证错误)。
响应式表单验证
响应式表单是另一种 Angular 表单机制,让我们实现更高级的表单逻辑和验证。它允许我们以响应式编程的方式来处理表单,使用了 RxJS 观察者模式来订阅和管理表单元素的值和验证状态。响应式表单需要使用 FormControl
、FormGroup
和 FormArray
等类来创建表单控件。我们可以在组件类中使用这些类来创建表单控件,然后将它们绑定到模板中。下面是一个响应式表单验证的示例代码:
-- -------------------- ---- ------- ------ - --------- - ---- ---------------- ------ - ------------ ------------ ---------- ---------- - ---- ----------------- ------------ --------- ------------------------ --------- - ----- ------------------------------ ------------------------ ---- ------------------ ---------------------------------- -- ------------------ ------ -------------------------------- ------ ----------- ------------- -------------------------- --------------------- ---- ------------------ ---------------------- -- ------------------ ---- ----------------------------------------- -- --------------- ---- ------------------------------------------ ---- -- -- ----- - ---------- ----------- ------ ------ ---- ------------------ ---------------------------------- -- ------------------ ------ -------------------------------- ------ --------------- ------------- -------------------------- --------------------- ---- ------------------ ---------------------- -- ------------------ ---- ----------------------------------------- -- --------------- ---- ------------------------------------------ ---- -- -- ----- - ---------- ----------- ------ ------ ------- ------------- ---------- ------------ ---------------------------------------------------- ------- -- ------- ------------ ------------- - ------------- ---- --- -- ------ ----- ------------------------- - ----------------- ---------- ------------------- --- ------------ - --------------------- - ---------- ----------- --- --------------- --------------------- -------------------------- ----------- --- --------------- --------------------- ------------------------- --- - --- ---------- - ------ -------------------------------------- - --- ---------- - ------ -------------------------------------- - ---------- - ----------------------------------------- - -
在上面的代码中,我们使用了 FormControl
、FormGroup
和 FormBuilder
来创建表单控件(即表单元素)。使用 FormControl
来创建单个表单控件,使用 FormGroup
来创建一组相关表单控件(即表单区域)。我们还使用了 FormBuilder
来简化表单控件的创建过程。
在模板中使用 [formGroup]
来绑定表单,使用 formControlName
来绑定单个表单控件。使用 *ngIf
来根据验证状态显示错误消息。我们还添加了一些 CSS 样式来显示验证错误样式。
自定义验证器
如果我们需要自定义表单验证逻辑,则可以创建自定义验证器。自定义验证器是一个函数,它会接收一个 AbstractControl
(即表单控件)对象,并返回一个验证错误对象,如果验证通过,则返回 null
。我们可以创建一个自定义验证器函数,并将它添加到表单控件的验证器列表中,如下所示:
import { AbstractControl, ValidationErrors, ValidatorFn } from '@angular/forms'; export function forbiddenNameValidator(nameRe: RegExp): ValidatorFn { return (control: AbstractControl): ValidationErrors | null => { const forbidden = nameRe.test(control.value); return forbidden ? { 'forbiddenName': { value: control.value } } : null; }; }
在上面的代码中,我们创建了一个 forbiddenNameValidator
函数来验证表单元素的值是否与给定的正则表达式匹配。如果验证失败,则返回错误对象 { 'forbiddenName': { value: control.value } }
。
然后,我们可以将 forbiddenNameValidator
函数添加到表单控件的验证器列表中,如下所示:
-- -------------------- ---- ------- ------ - --------- - ---- ---------------- ------ - ------------ ------------ ---------- ---------- - ---- ----------------- ------ - ---------------------- - ---- ----------------------------- ------------ --------- ------------------------ --------- - ----- ------------------------------ ------------------------ ---- ------------------ ---------------------------------- -- ------------------ ------ -------------------------------- ------ ----------- ------------- -------------------------- --------------------- ---- ------------------ ---------------------- -- ------------------ ---- ----------------------------------------- -- --------------- ---- ------------------------------------------ ---- -- -- ----- - ---------- ----------- ---- ---------------------------------------------- ------ ------- ------------ ------ ------ ---- ------------------ ---------------------------------- -- ------------------ ------ -------------------------------- ------ --------------- ------------- -------------------------- --------------------- ---- ------------------ ---------------------- -- ------------------ ---- ----------------------------------------- -- --------------- ---- ------------------------------------------ ---- -- -- ----- - ---------- ----------- ------ ------ ------- ------------- ---------- ------------ ---------------------------------------------------- ------- -- ------- ------------ ------------- - ------------- ---- --- -- ------ ----- ------------------------- - ----------------- ---------- ------------------- --- ------------ - --------------------- - ---------- ----------- --- --------------- - -------------------- ------------------------ ----------------------------- --- ----------- --- --------------- - -------------------- ----------------------- -- --- - --- ---------- - ------ -------------------------------------- - --- ---------- - ------ -------------------------------------- - ---------- - ----------------------------------------- - -
在上面的代码中,我们将 forbiddenNameValidator
函数添加到 username
表单控件的验证器列表中。如果用户名包含 'foo',则表单验证将失败,并显示错误消息。
异步表单验证器
有时,我们需要在 Angular 表单中实现异步表单验证逻辑,例如,从服务器端验证用户名是否已经被占用。在这种情况下,我们需要使用异步表单验证器。
异步表单验证器是一个返回 Observable 或 Promise 的函数。当有数据改变时,Angular 将调用异步验证器并等待它返回可观察对象的结果。如果观察到错误,则认为表单验证失败。
下面是一个示例异步验证器的代码:
-- -------------------- ---- ------- ------ - ---------------- --------------- ---------------- - ---- ----------------- ------ - ---------- - ---- ------- ------ - --- - ---- ----------------- ------ ----- ----------------------- ---------- -------------- - ----------------- ----------------- ------------------------ - ----- - --------------------------- - ----- - ------ --------------------------------------- ----------- -- -------- - - ---------------- ---- - - ------ -- - ----------------------- -------- ------------------- - ------ --------------------------- -- -------- ---- ------- - -
异步验证器的核心是在 validate
方法中进行异步验证。在上面的代码中,我们简单地使用 checkUsername
方法模拟了一个 HTTP 请求,该方法返回一个具有延迟的可观察对象。我们使用 map
运算符来转换结果,根据结果返回验证错误消息或 null
。
然后,我们可以将异步验证器添加到表单控件的验证器列表中,如下所示:
-- -------------------- ---- ------- ------ - --------- - ---- ---------------- ------ - ------------ ------------ ---------- ---------- - ---- ----------------- ------ - ----------------------- - ---- ------------------------------ ------------ --------- ------------------------ --------- - ----- ------------------------------ ------------------------ ---- ------------------ ---------------------------------- -- ------------------ ------ -------------------------------- ------ ----------- ------------- -------------------------- --------------------- ---- ------------------ ---------------------- -- ------------------ ---- ----------------------------------------- -- --------------- ---- ------------------------------------------ ---- -- -- ----- - ---------- ----------- ---- ---------------------------------------------- -- ------- ------------ ------ ------ ---- ------------------ ---------------------------------- -- ------------------ ------ -------------------------------- ------ --------------- ------------- -------------------------- --------------------- ---- ------------------ ---------------------- -- ------------------ ---- ----------------------------------------- -- --------------- ---- ------------------------------------------ ---- -- -- ----- - ---------- ----------- ------ ------ ------- ------------- ---------- ------------ ---------------------------------------------------- ------- -- ------- ------------ ------------- - ------------- ---- --- -- ------ ----- ------------------------- - ----------------- ---------- ------------------- --- ------------ ------- ------------------------ ------------------------ - --------------------- - ---------- ----------- --- --------------- - -------------------- ----------------------- -- ------------------------------------------------------------------ ----------- --- --------------- - -------------------- ----------------------- -- --- - --- ---------- - ------ -------------------------------------- - --- ---------- - ------ -------------------------------------- - ---------- - ----------------------------------------- - -
在上面的代码中,我们将 UniqueUsernameValidator
类的实例传递给组件构造函数,并将其添加到 username
表单控件的验证器列表中。在 asyncValidator
列表中添加异步验证器时,我们需要将验证器函数绑定到其实例上。如果 UniqueUsernameValidator
的 validate
方法返回的观察对象发出 usernameTaken
错误,则表单验证失败,并显示错误消息。
结论
在 Angular 应用中实现优雅的表单验证需要使用 Angular 内置表单指令和响应式表单机制。我们还可以添加自定义验证器和异步验证器来实现更复杂的验证逻辑。希望本文对你有所帮助,如果你有其他有关 Angular 的问题,可以访问 Angular 官网 获取更多信息。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/670a0de4d91dce0dc87e2baa