Angular Reactive Forms -- Model-Driven Forms响应式表单
Angular 4.x 中有两种表单:
Template-Driven Forms - 模板驱动式表单 (类似于 AngularJS 1.x 中的表单 ) 官方文档:https://v2.angular.cn/docs/ts/latest/guide/forms.html
Reactive Forms (Model-Driven Forms) - 响应式表单 官方文档: https://v2.angular.cn/docs/ts/latest/guide/reactive-forms.html
Template-Driven Forms vs Reactive Forms
Template-Driven Forms (模板驱动表单) 的特点
使用方便
适用于简单的场景
通过 [(ngModel)] 实现数据双向绑定
最小化组件类的代码
不易于单元测试
- 异步的,模板驱动表单会委托指令来创建它们的表单控件。 为了消除“检查完后又变化了”的错误,这些指令需要消耗一个以上的变更检测周期来构建整个控件树。 这意味着在从组件类中操纵任何控件之前,我们都必须先等待一个节拍。
Reactive Forms (响应式表单) 的特点
比较灵活
适用于复杂的场景
简化了HTML模板的代码,把验证逻辑抽离到组件类中
方便的跟踪表单控件值的变化
易于单元测试
- 同步的 ,使用响应式表单,我们会在代码中创建整个表单控件树。 我们可以立即更新一个值或者深入到表单中的任意节点,因为所有的控件都始终是可用的。
使用 reactive forms 表单前,我们必须在 @NgModule
中导入 @angular/forms
库中的 ReactiveFormsModule
:
import { ReactiveFormsModule } from '@angular/forms'; @NgModule({
imports: [
...,
ReactiveFormsModule
],
declarations: [...],
bootstrap: [...]
})
export class AppModule {}
友情提示:若使用 reactive forms,则导入 ReactiveFormsModule;若使用 template-driven 表单,则导入 FormsModule。
FormControl 和 FormGroup
FormControl - 它是一个为单个表单控件提供支持的类,可用于跟踪控件的值和验证状态,此外还提供了一系列公共API。
使用示例:
ngOnInit() {
this.myControl = new FormControl('Semlinker');
}
FormGroup - 包含是一组 FormControl 实例,可用于跟踪 FormControl 组的值和验证状态,此外也提供了一系列公共API。
使用示例:
ngOnInit() {
this.myGroup = new FormGroup({
name: new FormControl('Semlinker'),
location: new FormControl('China, CN')
});
}
现在我们已经创建了 FormControl
和 FormGroup
实例,接下来我们来看一下如何使用:
<form novalidate [formGroup]="myGroup">
Name: <input type="text" formControlName="name">
Location: <input type="text" formControlName="location">
</form>
注意事项:Template-Driven Forms 中介绍的 ngModel
和 name=""
属性,已经被移除了。这是一件好事,让我们的模板更简洁。
上面示例中,我们必须使用 [formGroup]
绑定我们创建的 myGroup
对象,除此之外还要使用 formControlName
指令,绑定我们创建的 FormControl
控件。此时的表单结构如下:
FormGroup -> 'myGroup'
FormControl -> 'name'
FormControl -> 'location'
User interface
signup.interface.ts
export interface User {
name: string;
account: {
email: string;
confirm: string;
}
}
与之对应的表单结构如下:
FormGroup -> 'user'
FormControl -> 'name'
FormGroup -> 'account'
FormControl -> 'email'
FormControl -> 'confirm'
是的,我们可以创建嵌套的 FormGroup 集合!让我们更新一下组件 (不包含初始数据):
import { Component, OnInit } from '@angular/core';
import { FormControl, FormGroup } from '@angular/forms'; @Component({...})
export class SignupFormComponent implements OnInit {
user: FormGroup;
ngOnInit() {
this.user = new FormGroup({
name: new FormControl(''),
account: new FormGroup({
email: new FormControl(''),
confirm: new FormControl('')
})
});
}
}
如果我们想要设置初始数据,我们可以按照上述示例进行设置。通常情况下,我们通过服务端提供的 API 接口来获取表单的初始信息。
绑定FormGroup模型
<form novalidate [formGroup]="user">
<label>
<span>Full name</span>
<input
type="text"
placeholder="Your full name"
formControlName="name">
</label>
<div formGroupName="account">
<label>
<span>Email address</span>
<input
type="email"
placeholder="Your email address"
formControlName="email">
</label>
<label>
<span>Confirm address</span>
<input
type="email"
placeholder="Confirm your email address"
formControlName="confirm">
</label>
</div>
<button type="submit">Sign up</button>
</form>
现在 FormGroup
与 FormControl
对象与 DOM 结构的关联信息如下:
// JavaScript APIs
FormGroup -> 'user'
FormControl -> 'name'
FormGroup -> 'account'
FormControl -> 'email'
FormControl -> 'confirm' // DOM bindings
formGroup -> 'user'
formControlName -> 'name'
formGroupName -> 'account'
formControlName -> 'email'
formControlName -> 'confirm'
当使用模板驱动的表单时,为了获取 f.value
表单的值,我们需要先执行 #f="ngForm"
的操作。而对于使用响应式的表单,我们可以通过以下方式,方便的获取表单的值:
{{ user.value | json }} // { name: '', account: { email: '', confirm: '' }}
Reactive submit
跟模板驱动的表单一样,我们可以通过 ngSubmit
输出属性,处理表单的提交逻辑:
<form novalidate (ngSubmit)="onSubmit(user)" [formGroup]="user">
...
</form>
需要注意的是,我们使用 user
对象作为 onSubmit()
方法的参数,这使得我们可以获取表单对象的相关信息,具体处理逻辑如下:
export class SignupFormComponent {
user: FormGroup;
onSubmit({ value, valid }: { value: User, valid: boolean }) {
console.log(value, valid);
}
}
上面代码中,我们使用 Object destructuring
(对象解构) 的方式,从user
对象中获取 value
和 valid
属性的值。其中 value
的值,就是 user.value
的值。在实际应用中,我们是不需要传递 user
参数的:
export class SignupFormComponent {
user: FormGroup;
onSubmit() {
console.log(this.user.value, this.user.valid);
}
}
表单的数据绑定方式和提交逻辑已经介绍完了,是该介绍表单实际应用中,一个重要的环节 — 表单验证。
Reactive error validation
接下来我们来为表单添加验证规则,首先我们需要从 @angular/forms
中导入 Validators
。具体使用示例如下:
ngOnInit() {
this.user = new FormGroup({
name: new FormControl('', [Validators.required, Validators.minLength()]),
account: new FormGroup({
email: new FormControl('', Validators.required),
confirm: new FormControl('', Validators.required)
})
});
}
通过以上示例,我们可以看出,如果表单控制包含多种验证规则,可以使用数组声明多种验证规则。若只包含一种验证规则,直接声明就好。通过这种方式,我们就不需要在模板的输入控件中添加 required
属性。接下来我们来添加表单验证失败时,不允许进行表单提交功能:
<form novalidate (ngSubmit)="onSubmit(user)" [formGroup]="user">
...
<button type="submit" [disabled]="user.invalid">Sign up</button>
</form>
那么问题来了,我们要如何获取表单控件的验证信息?我们可以使用模板驱动表单中介绍的方式,具体如下:
<form novalidate [formGroup]="user">
{{ user.controls.name?.errors | json }}
</form>
友情提示:?.prop 称为安全导航操作符,用于告诉 Angular prop 的值可能不存在。
此外我们也可以使用 FormGroup
对象提供的 API,来获取表单控件验证的错误信息:
<form novalidate [formGroup]="user">
{{ user.get('name').errors | json }}
</form>
完整代码:
import { Component, OnInit } from '@angular/core';
import { FormControl, FormGroup, Validators } from '@angular/forms';
import { User } from './signup.interface';
@Component({
selector: 'signup-form',
template: `
<form novalidate (ngSubmit)="onSubmit(user)" [formGroup]="user">
<label>
<span>Full name</span>
<input type="text" placeholder="Your full name" formControlName="name">
</label>
<div class="error" *ngIf="user.get('name').hasError('required') &&
user.get('name').touched">
Name is required
</div>
<div class="error" *ngIf="user.get('name').hasError('minlength') &&
user.get('name').touched">
Minimum of characters
</div>
<div formGroupName="account">
<label>
<span>Email address</span>
<input type="email" placeholder="Your email address" formControlName="email">
</label>
<div
class="error"
*ngIf="user.get('account').get('email').hasError('required') &&
user.get('account').get('email').touched">
Email is required
</div>
<label>
<span>Confirm address</span>
<input type="email" placeholder="Confirm your email address"
formControlName="confirm">
</label>
<div
class="error"
*ngIf="user.get('account').get('confirm').hasError('required') &&
user.get('account').get('confirm').touched">
Confirming email is required
</div>
</div>
<button type="submit" [disabled]="user.invalid">Sign up</button>
</form>
`
})
export class SignupFormComponent implements OnInit {
user: FormGroup;
constructor() {}
ngOnInit() {
this.user = new FormGroup({
name: new FormControl('', [Validators.required, Validators.minLength()]),
account: new FormGroup({
email: new FormControl('', Validators.required),
confirm: new FormControl('', Validators.required)
})
});
}
onSubmit({ value, valid }: { value: User, valid: boolean }) {
console.log(value, valid);
}
}
功能是实现了,但创建 FormGroup
对象的方式有点繁琐,Angular 团队也意识到这点,因此为我们提供 FormBuilder
,来简化上面的操作。
Simplifying with FormBuilder
首先我们需要从 @angular/forms
中导入 FormBuilder
:
import { FormBuilder, FormGroup, Validators } from '@angular/forms'; export class SignupFormComponent implements OnInit {
user: FormGroup;
constructor(private fb: FormBuilder) {}
...
}
使用FormBuilder:
@Component({...})
export class SignupFormComponent implements OnInit {
user: FormGroup;
constructor(private fb: FormBuilder) {}
ngOnInit() {
this.user = this.fb.group({
name: ['', [Validators.required, Validators.minLength()]],
account: this.fb.group({
email: ['', Validators.required],
confirm: ['', Validators.required]
})
});
}
onSubmit({ value, valid }: { value: User, valid: boolean }) {
console.log(value, valid);
}
}
转自:https://segmentfault.com/a/1190000009041192
Angular Reactive Forms -- Model-Driven Forms响应式表单的更多相关文章
- ng2响应式表单-翻译与概括官网REACTIVE FORMS页面
本文将半翻译半总结的讲讲ng2官网的另一个未翻译高级教程页面. 原文地址. 文章目的是使用ng2提供的响应式表单技术快速搭出功能完善丰富的界面表单组件. 响应式表单是一项响应式风格的ng2技术,本文将 ...
- Angular2响应式表单-翻译与概括官网REACTIVE FORMS页面
本文将半翻译半总结的讲讲ng2官网的另一个未翻译高级教程页面. 原文地址. 文章目的是使用ng2提供的响应式表单技术快速搭出功能完善丰富的界面表单组件. 响应式表单是一项响应式风格的ng2技术,本文将 ...
- Angular11 模板表单、响应式表单(自定义验证器)、HTTP、表单元素双向绑定
1 模板表单 模型通过指令隐式创建 技巧01:需要在模块级别引入 FormsModule ,通常在共享模块中引入再导出,然后在需要用到 FormsModule 的模块中导入共享模块就可以啦 impor ...
- Angular2响应式表单
本文将半翻译半总结的讲讲ng2官网的另一个未翻译高级教程页面. 原文地址. 文章目的是使用ng2提供的响应式表单技术快速搭出功能完善丰富的界面表单组件. 响应式表单是一项响应式风格的ng2技术,本文将 ...
- angular6的响应式表单
1:在AppModule模块里面引入 ReactiveFormsModule 要使用响应式表单,就要从@angular/forms包中导入ReactiveFormsModule,并把它添加到你的NgM ...
- Angular之响应式表单 ( Reactive Forms )
项目结构 一 首页 ( index.html ) <!doctype html> <html lang="en"> <head> <met ...
- 【译】用 Chart.js 做漂亮的响应式表单
数据包围着我们.虽然搜索引擎和其他应用都对基于文本方式表示的数据偏爱有加,但人们发现可视化是更容易理解的一种方式.今年初,SitePoint 发表了 Aurelio 的文章< Chart.js简 ...
- angular响应式表单 - 状态字段
用于表单验证的过程: touched,untoched pristine,dirty pending
- angular 响应式表单
随机推荐
- Vue 脱坑记 - 查漏补缺(汇总下群里高频询问的xxx及给出不靠谱的解决方案)
前言 发现群里有些问题的提问重复率太高了,每次都去回答,回答的贼烦.这里做一个大体的汇总,废话不多说,直接开始给出方案,不是手把手..若是连问题和解决都看不懂的..应该去补充下基础知识 问题汇总 Q: ...
- D3基础--数轴
转载请注明出处! 概述: 与比例尺类似,D3的数轴实际上也使用来定义参数的函数.但与比例尺不同的是,调用数轴函数并不会返回值,而是会生成数轴相关的可见元素.包括:轴线,标签和刻度. 但是要注意数轴函数 ...
- 集群搭建之Hive配置要点
注意点: 在启动Hive 的时候要先启动Hadoop和MySQL服务. Mysql 和 Hive 搭建在 yan00机器上. part1:MySQL配置相关 安装和配置相关命令: Yum instal ...
- Windbg 脚本命令简介 二, Windbg command
Windbg 脚本命令简介 二, Windbg script command $<, $><, $$<, $$><, $$>a< (Run Scri ...
- Springboot @ResponseBody返回中文乱码
最近我在把Spring 项目改造Springboot,遇到一个问题@ResponseBody返回中文乱码,因为response返回的content-type一直是application/json;ch ...
- Java中名词的解释
在上一篇中说到了Java的四大特性,里面出现了很多名次,包括以后学习Java中也会出现很多常用到的名次,对初学者来说可能不知道是什么意思,或者是对这些刺耳的理解不是特别透彻,这里我就我自己的理解来解释 ...
- 解决:启动项目报错 java.lang.UnsatisfiedLinkError: D:\Java\apache-tomcat-8.0.17\bin\tcnative-1.dll: Can't load IA 32-bit .dll on a AMD 64-bit platform
启动项目报错如下: java.lang.UnsatisfiedLinkError: D:\Java\apache-tomcat-8.0.17\bin\tcnative-1.dll: Can't loa ...
- Java:反射与代理
Java世界的繁荣反射这一特性有很大功劳,可以获取全面的类型信息. /** * */ package ref; import java.lang.reflect.Field; import java. ...
- 普通平衡树Tyvj1728、luogu P3369 (splay)
存个模板,这次是splay的: 题目见这个题解: <--(鼠标移到这儿) 代码如下: #include<cstdio> #define INF 2147483647 using na ...
- Java线程的周期及五种状态
线程的生命周期及五种基本状态 关于Java中线程的生命周期,首先看一下下面这张较为经典的图: 上图中基本上囊括了Java中多线程各重要知识点.掌握了上图中的各知识点,Java中的多线程也就基本上掌握了 ...