如何在 Angular 中使用响应式表单

简介: 如何在 Angular 中使用响应式表单

简介

Angular 提供了两种处理表单的方式:模板驱动表单响应式表单(也称为 模型驱动表单)。模板驱动表单是在 Angular 中处理表单的默认方式。使用模板驱动表单时,模板指令被用来构建表单的内部表示。而使用响应式表单时,你需要在组件类中构建自己的表单表示。

以下是响应式表单的一些优势:

  • 使用自定义验证器
  • 动态改变验证规则
  • 动态添加表单字段

在本文中,你将探索如何将响应式表单应用到一个示例 Angular 应用程序中。

先决条件

如果你想跟着本文操作,你需要:

  • 本地安装 Node.js,你可以按照《如何安装 Node.js 并创建本地开发环境》进行操作。

本文假设你具有一些 Angular 的基础知识。

本文还假设你是在使用 @angular/cli 生成的全新 Angular 项目进行构建。如果你刚开始使用 Angular CLI,你可以参考本文。

本教程经过 Node v15.1.0、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-example --style=css --routing=false --skip-tests

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

进入新创建的项目目录:

cd angular-reactive-forms-example

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

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

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 —— 向组件模板添加表单

使用响应式表单时,逻辑完全在组件类中声明。

在你的代码编辑器中打开 app.component.html 并添加以下代码:

<form [formGroup]="myForm" (ngSubmit)="onSubmit(myForm)">
  <div>
    <label>
      Name:
      <input formControlName="name" placeholder="Your name">
    </label>
  </div>
  <div>
    <label>
      Email:
      <input formControlName="email" placeholder="Your email">
    </label>
  </div>
  <div>
    <label>
      Message:
      <input formControlName="message" placeholder="Your message">
    </label>
  </div>
  <button type="submit">Send</button>
</form>

这段代码将创建一个包含三个字段(nameemailmessage)的表单。还将有一个标签为 “Send” 的 "submit" 按钮。在提交表单时,将调用 onSubmit(myForm) 方法。

让我们来分解一下:

  • formGroup:表单将在组件类中被视为 FormGroup,因此 formGroup 指令允许给表单组指定一个名称。
  • ngSubmit:这是在提交表单时触发的事件。
  • formControlName:每个表单字段应该有一个 formControlName 指令,其值将在组件类中使用。

到此为止,你应该已经有了一个使用表单的组件模板。

步骤 3 —— 构建组件类

接下来,在组件类中,你将定义 FormGroupFormGroup 内的各个 FormControl

如果在 newing FormControl 时提供了一个值,它将被用作字段的初始值。

注意 FormGroupFormControl 的名称与模板中使用的名称相同。还要注意你如何在 ngOnInit 生命周期钩子中初始化 FormGroup

import { Component, OnInit } from '@angular/core';
import { FormControl, FormGroup } from '@angular/forms';
@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
  myForm: FormGroup;
  ngOnInit() {
    this.myForm = new FormGroup({
      name: new FormControl('Sammy'),
      email: new FormControl(''),
      message: new FormControl('')
    });
  }
  onSubmit(form: FormGroup) {
    console.log('Valid?', form.valid); // true or false
    console.log('Name', form.value.name);
    console.log('Email', form.value.email);
    console.log('Message', form.value.message);
  }
}

在本教程中,onSubmit 方法实际上并没有将提交的表单值传递给任何外部服务或服务器。它用于展示你如何访问表单的有效性和 FormControl 的值。

到此为止,你可以编译你的应用程序并在 web 浏览器中打开它。在为 nameemailmessage 输入值并点击 Submit 后,控制台日志将显示这些值。

第四步 — 更新组件类以使用 FormBuilder

ngOnInit 中的表单构建可以使用 FormBuilder 辅助程序进行重写。这样可以避免对表单组和表单控件进行 newing

在代码编辑器中打开 app.component.ts,移除 FormControl 并用 FormBuilder 替换 FormGroup

import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup } from '@angular/forms';
@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({
      name: 'Sammy',
      email: '',
      message: ''
    });
  }
  onSubmit(form: FormGroup) {
    console.log('Valid?', form.valid); // true or false
    console.log('Name', form.value.name);
    console.log('Email', form.value.email);
    console.log('Message', form.value.message);
  }
}

使用 FormBuilder 的这段代码减少了创建 FormGroup 的样板代码。

第五步 — 更新组件类以使用 Validators

Validators 类添加到你的导入中,并使用数组而不是简单的字符串值来声明表单控件。

数组中的第一个值是初始表单值,第二个值是要使用的验证器。请注意,可以通过将它们包装成数组来在同一个表单控件上使用多个验证器。

在代码编辑器中打开 app.component.ts,添加 Validators

import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
@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({
      name: ['Sammy', Validators.required],
      email: ['', [Validators.required, Validators.email]],
      message: ['', [Validators.required, Validators.minLength(15)]],
    });
  }
  onSubmit(form: FormGroup) {
    console.log('Valid?', form.valid); // true or false
    console.log('Name', form.value.name);
    console.log('Email', form.value.email);
    console.log('Message', form.value.message);
  }
}

这段代码为 nameemailmessage 字段添加了 required。它还确保 email 值使用有效电子邮件地址的格式。它还确保 message 值至少为 15 个字符长。

如果这些表单要求中的任何一个未通过,valid 值将为 false。如果所有这些表单要求都通过,valid 值将为 true

第六步 — 在模板中访问表单值和有效性

在模板中,可以访问每个 FormControl 的值和有效性,以及整个表单组的值和有效性。

打开 app.component.html,使用 *ngIf 来显示反馈消息,告诉用户表单值无效:

<form [formGroup]="myForm" (ngSubmit)="onSubmit(myForm)">
  <div>
    <label>
      Name:
      <input formControlName="name" placeholder="Your name">
    </label>
    <div *ngIf="myForm.get('name').invalid && (myForm.get('name').dirty || myForm.get('name').touched)">
      Please provide a name.
    </div>
  </div>
  <div>
    <label>
      Email:
      <input formControlName="email" placeholder="Your email">
    </label>
    <div *ngIf="myForm.get('email').invalid && (myForm.get('email').dirty || myForm.get('email').touched)">
      Please provide a valid email address.
    </div>
  </div>
  <div>
    <label>
      Message:
      <input formControlName="message" placeholder="Your message">
    </label>
    <div *ngIf="myForm.get('message').invalid && (myForm.get('message').dirty || myForm.get('message').touched)">
      Messages must be at least 15 characters long.
    </div>
  </div>
  <button type="submit" [disabled]="myForm.invalid">Send</button>
</form>

这段代码检查用户是否与字段交互(dirtytouched)。然后,如果值未通过验证要求,它将显示错误消息。Send 按钮也将在解决表单值的所有问题之前被禁用。

有多种方法可以检索表单控件的值。此示例使用 myForm.get('name'),它等同于 myForm.controls.name。可以使用 .hasError('required').errors.required 检索错误信息。

结论

在本文中,您探讨了如何将响应式表单应用于一个示例 Angular 应用程序。您使用了 FormControlFormGroupFormBuilderValidators 来构建一个带有验证的示例表单。如需了解更多功能,请参考官方文档。

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


目录
相关文章
|
17天前
|
开发者 Java Spring
JSF 牵手社交登录,如魔法风暴席卷 Web 世界,开启震撼便捷登录之旅!
【8月更文挑战第31天】在互联网时代,便捷登录成为用户的核心需求。社交登录凭借其便捷性、安全性和社交化的特点,在各类Web应用中广泛应用。JavaServer Faces(JSF),作为一款流行的Java Web框架,能够轻松集成社交登录功能,显著提升用户体验。本文详细介绍社交登录的优势,并提供两种JSF集成社交登录的常见方法:一是利用Spring Social等第三方库简化开发;二是自行实现社交登录流程。开发者可根据项目需求选择适合的方案。
24 0
|
17天前
|
开发者 容器 Docker
JSF与Docker,引领容器化浪潮!让你的Web应用如虎添翼,轻松应对高并发!
【8月更文挑战第31天】在现代Web应用开发中,JSF框架因其实用性和灵活性被广泛应用。随着云计算及微服务架构的兴起,容器化技术变得日益重要,Docker作为该领域的佼佼者,为JSF应用提供了便捷的部署和管理方案。本文通过基础概念讲解及示例代码展示了如何利用Docker容器化JSF应用,帮助开发者实现高效、便携的应用部署。同时也提醒开发者注意JSF与Docker结合使用时可能遇到的限制,并根据实际情况做出合理选择。
26 0
|
1月前
Angular 中的响应式表单:监听变化
Angular 中的响应式表单:监听变化
21 0
|
1月前
|
JavaScript 前端开发
如何在 Angular 中为响应式表单创建自定义验证器
如何在 Angular 中为响应式表单创建自定义验证器
12 0
|
1月前
|
JavaScript
如何使用 ControlValueAccessor 在 Angular 中创建自定义表单控件
如何使用 ControlValueAccessor 在 Angular 中创建自定义表单控件
11 0
|
前端开发 数据安全/隐私保护 CDN
Angular最新教程-第六节编写响应式导航栏
Angular最新教程-第六节编写响应式导航栏
405 0
Angular最新教程-第六节编写响应式导航栏
|
API
Angular 2.x折腾记 :(7) 初步了解表单:模板驱动及数据驱动及脱坑要点
表单在整个系统中的作用相当重要,这里主要扯下响应表单的实现方式。 首先需要操作表单的模块引入这两个模块; import { FormsModule, ReactiveFormsModule } from '@angular/forms';
162 0
|
JavaScript
Angular Form (响应式Form) 学习笔记
Angular Form (响应式Form) 学习笔记
180 0
Angular Form (响应式Form) 学习笔记
|
JSON 数据安全/隐私保护 数据格式
Angular4总结(六)—— 表单
模版式表单(FormsModule) 这个方法只适用于简单的表单需求,因为它受限于html模版。 可以使用的指令为: NgForm. ———> 隐式创建FormGroup实例 NgModel. ———>隐式创建FormControl实例 NgModelGroup. ————>隐式创建FormGroup实例,与NgForm类似,只不过NgModelGroup相当于在外面又加了一层外壳,然后这个外壳,作为了NgForm的子属性 NgForm相当于传统的页面form表单,表单中所有定义的属性,需要写上NgModel,这样NgForm就知道所有NgModel的存在了。
1384 0
|
JavaScript
Angular4总结(四)—— 数据绑定,响应式,管道
数据绑定 angular4中默认的数据绑定都是单向的。可分为: 插值表达式形式(Dom属性绑定) <p>{{test}}<p> Dom 属性绑定流程: 控制器中定义了一个属性,值发生了改变 对应的dom的value被附上改变了的值 渲染后的页面上也会出现刚刚的值 这一切操作都和html属性不发生任何关系 html属性绑定,使用中括号 <img [src]="imgUrl"/> //如果没有写这个方括号,angular会把属性右侧的值作为字符串进行赋值,而非表达式 基本Html属性绑定 CSS属性绑定 这种形式是全有或者全无的。
1390 0