angular6的响应式表单的实现


Posted in Javascript onOctober 10, 2018

1:在AppModule模块里面引入 ReactiveFormsModule

要使用响应式表单,就要从@angular/forms包中导入ReactiveFormsModule,并把它添加到你的NgModule的imports数组中。

import { ReactiveFormsModule } from '@angular/forms';

@NgModule({
 imports: [
 // other imports ...
 ReactiveFormsModule
 ],
})
export class AppModule { }

2:创建一个新的组件

ng g c NameEditor

3:请在组件中导入 FormControl 类

FormControl类是angular响应式表单最基本的构造快,要注册单个的表单控件,请在组件中导入FormControl类,并创建一个FormControl的新实例,把它保存在某个属性里面。

import { Component } from '@angular/core';
import { FormControl } from '@angular/forms';

@Component({
 selector: 'app-name-editor',
 templateUrl: './name-editor.component.html',
 styleUrls: ['./name-editor.component.css']
})

export class NameEditorComponent {
 name = new FormControl('');
}

4:在组件的模板中注册一个表单控件

修改模板,为表单控件添加 formControl 绑定,formControl 是由 ReactiveFormsModule 中的 FormControlDirective 提供的。

<label>
 Name:
 <input type="text" [formControl]="name">
</label>

<p>
 Value: {{ name.value }}
</p>

使用这种模板绑定语法,把该表单控件注册给了模板中名为 name 的输入元素。这样,表单控件和 DOM
元素就可以互相通讯了:视图会反映模型的变化,模型也会反映视图中的变化。

5:替换表单控件的值

FormControl 提供了一个setValue()方法,他会修改这个表单控件的值。

js

updateName() {
  this.name.setValue('Nancy');
 }

html

<label>
 Name:
 <input type="text" [formControl]="name">
</label>
<p>
 Value:{{name.value}}
</p>
<p>
 <button (click)="updateName()">Update Name</button>
</p>

在这个例子中,你只使用单个控件FormControl,但是当调用 FormGroup 或 FormArray 的 setValue()方法时,传入的值就必须匹配控件组或控件数组的结构才行

6:把表单控件分组

FormControl的实例能控制单个输入框所对应的控件,FormGroup可以控制一组FormControl实例的表单状态,当创建FormGroup时,其中的每一个控件都会根据名字进行跟踪

1>:创建新的组件

ng g c ProfileEditor

2>:导入 FormGroup 和 FormControl 类并且创建 FormGroup实例

import { Component } from '@angular/core';
import { FormGroup, FormControl } from '@angular/forms';
 
@Component({
 selector: 'app-profile-editor',
 templateUrl: './profile-editor.component.html',
 styleUrls: ['./profile-editor.component.css']
})

export class ProfileEditorComponent {
 profileForm = new FormGroup({
 firstName: new FormControl(''),
 lastName: new FormControl(''),
 });
}

现在这些单独的控件FormControl被收集到了一个控件组中FormGroup, FormGroup 实例拥有和 FormControl 实例相同的属性(比如 value、untouched)和方法(比如 setValue())。

3>:关联FormGroup的模型和视图

FormGroup能追踪每个单独控件FormControl的状态和变化,如果其中某个控件的状态或值变化了,父控件也会一次新的状态变更或值变更事件

<form [formGroup]="profileForm">
 
 <label>
 First Name:
 <input type="text" formControlName="firstName">
 </label>

 <label>
 Last Name:
 <input type="text" formControlName="lastName">
 </label>

</form>

profileForm通过[formGroup]指令绑定到了 form元素,在该模型和表单中的输入框之间创建了一个通讯层,FormControlName 指令提供的 formControlName 属性把每个输入框和 FormGroup 中定义的表单控件绑定起来。

4>:关联FormGroup的模型和视图

html

<form [formGroup]="profileForm" (ngSubmit)="onSubmit()">
  <label>
  First Name:
  </label>
  <input type="text" formControlName="firstName">
 
  <label>
  Last Name:
  </label>
  <input type="text" formControlName="lastName">
 
  <button type="submit" >Submit</button>
 </form>

js

onSubmit () {
 console.warn(this.profileForm.value);
}

form 标签所发出的 submit 事件是原生 DOM 事件,通过点击类型为 submit 的按钮可以触发本事件

6:嵌套的表单组

js

profileForm = new FormGroup({
 firstName: new FormControl(''),
 lastName: new FormControl(''),
 address: new FormGroup({
  street: new FormControl(''),
  city: new FormControl(''),
  state: new FormControl(''),
  zip: new FormControl('')
 })
});

html

<form [formGroup]="profileForm" (ngSubmit)="onSubmit()">
 <label>
 First Name:
 </label>
 <input type="text" formControlName="firstName">
 <label>
 Last Name:
 </label>
 <input type="text" formControlName="lastName">

 <div formGroupName="address">
 <label>Streel</label>
 <input type="text" formControlName="street">
 <label>City</label>
 <input type="text" formControlName="city">
 <label>State</label>
 <input type="text" formControlName="state">
 <label>Zip Code</label>
 <input type="text" formControlName="zip">
 </div>

 <button type="submit" [disabled]="!profileForm.valid">Submit</button>
</form>

部分模型修改

html

<button (click)="updateProfile()">Update Profile</button>

js

updateProfile() {
  this.profileForm.patchValue({
  firstName: 'Nancy',
  address: {
   street: '123 Drew Street'
  }
  });
}

patchValue() 方法要针对模型的结构进行更新。patchValue() 只会更新表单模型中所定义的那些属性。

6:使用 FormBuilder 来生成表单控件

FormBuilder 服务提供了一些便捷方法来生成表单控件。

FormBuilder在幕后也使用同样的方式来创建和返回这些实例,只是用起来更简单。 下面会重构 ProfileEditor 组件,用FormBuilder 来代替手工创建这些 FormControl 和 FormGroup。

Step 1 - 导入 FormBuilder 类

import { FormBuilder } from '@angular/forms';

Step 2 - 注入FormBuild 服务

constructor(private fb: FormBuilder) { }

Step 3- 生成表单控件

FormBuilder 服务有三个方法:control()、group() 和 array()。这些方法都是工厂方法,用于在组件类中分别生成
FormControl、FormGroup 和 FormArray。

你可以使用 group() 方法,用和前面一样的名字来定义这些属性。这里,每个控件名对应的值都是一个数组,这个数组中的第一项是其初始值。你可以只使用初始值来定义控件,但是如果你的控件还需要同步或异步验证器,那就在这个数组中的第二项和

第三项提供同步和异步验证器。

import { Component } from '@angular/core';
import { FormBuilder } from '@angular/forms';
 
@Component({
 selector: 'app-profile-editor',
 templateUrl: './profile-editor.component.html',
 styleUrls: ['./profile-editor.component.css']
})
export class ProfileEditorComponent {
 profileForm = this.fb.group({
 firstName: ['张'],
 lastName: ['娉'],
 address: this.fb.group({
  street: [''],
  city: [''],
  state: [''],
  zip: ['']
 }),
 });
 
 constructor(private fb: FormBuilder) { }
}

7:简单的表单验证

如何把单个验证器添加到表单控件中,以及如何显示表单的整体状态。

Step 1 - 导入验证器函数

import { Validators } from '@angular/forms';

响应式表单包含了一组开箱即用的常用验证器函数。这些函数接收一个控件,用以验证并根据验证结果返回一个错误对象或空值。

Step 2 - 把字段设为必填

最常见的校验项是把一个字段设为必填项。本节描述如何为 firstName 控件添加“必填项”验证器。

在组件中,把静态方法 Validators.required 设置为 firstName 控件值数组中的第二项。

profileForm = this.fb.group({
 firstName: ['', Validators.required],
 lastName: [''],
 address: this.fb.group({
 street: [''],
 city: [''],
 state: [''],
 zip: ['']
 }),
});

HTML5 有一组内置的属性,用来进行原生验证,包括 required、minlength、maxlength等。虽然是可选的,不过你也可以在表单的输入元素上把它们添加为附加属性来使用它们。这里我们把 required 属性添加到 firstName输入元素上。

<input type="text" formControlName="firstName" required>

这些 HTML5 验证器属性可以和 Angular响应式表单提供的内置验证器组合使用。组合使用这两种验证器实践,可以防止在模板检查完之后表达式再次被修改导致的错误。

8:显示表单的状态

现在,你已经往表单控件上添加了一个必填字段,它的初始值是无效的(invalid)。这种无效状态冒泡到其父 FormGroup 中,也让这个 FormGroup 的状态变为无效的。你可以通过该 FormGroup 实例的 status 属性来访问其当前状态。

<p>
 Form Status: {{ profileForm.status }}
</p>

9:使用表单数组管理动态控件

FormArray 是 FormGroup 之外的另一个选择,用于管理任意数量的匿名控件,如果你事先不知道子控件的数量,FormArray是一个很好的选择

Step 1 - 导入 FormArray

import { FormArray } from '@angular/forms';

Step 2 - 定义 FormArray

为 profileForm 添加一个 aliases 属性,把它定义为 FormArray 类型。(FormBuilder 服务用于创建 FormArray 实例。)

profileForm = this.fb.group({
 firstName: ['张', Validators.required],
 lastName: ['以'],
 address: this.fb.group({
  street: [''],
  city: [''],
  state: [''],
  zip: ['']
 }),
 aliases: this.fb.array([
  this.fb.control('')
 ])
 });

Step 3 - 访问FormArray控件

通过 getter 来访问控件比较便捷,也容易复用

使用 getter 语法来创建一个名为 aliases 的类属性

get aliases() {
 
}

从父控件 FormGroup 中接收绰号的 FormArray 控件。

get aliases() {
 return this.profileForm.get('aliases') as FormArray;
}
addAlias() {
 this.aliases.push(this.fb.control(''));
}

Step 3 - 在模板中显示表单数组

在模型中定义了 aliases 的 FormArray 之后,你必须把它加入到模板中供用户输入,使用 formArrayName 在这个
FormArray 和模板之间建立绑定。

<div formArrayName="aliases">
 <h3>Aliases</h3> <button (click)="addAlias()">Add Alias</button>

 <div *ngFor="let address of aliases.controls; let i=index">
 <!-- The repeated alias template -->
 <label>
  Alias:
  <input type="text" [formControlName]="i">
 </label>
 </div>
</div>

每当新的 alias 加进来时,FormArray 就会基于这个索引号提供它的控件。这将允许你在每次计算根控件的状态和值时跟踪每个控件。

全部代码

html

<form [formGroup]="profileForm" (ngSubmit)="onSubmit()">
 <label>
 First Name:
 </label>
 <input type="text" formControlName="firstName" required>

 <label>
 Last Name:
 </label>
 <input type="text" formControlName="lastName">

 <div formGroupName="address">
 <h3>Address</h3>
 <label>Streel</label>
 <input type="text" formControlName="street">

 <label>City</label>
 <input type="text" formControlName="city">
 
 <label>State</label>
 <input type="text" formControlName="state">

 <label>Zip Code</label>
 <input type="text" formControlName="zip">
 </div>

 <div formArrayName="aliases">
 <h3>Aliases</h3>
 <button (click)="addAlias()">Add Alias</button>
 
 <div *ngFor="let address of aliases.controls; let i=index">
  <label>Alias</label>
  <input type="text" [formControlName]="i" >
 </div>
 </div>

 <button type="submit" [disabled]="!profileForm.valid">Submit</button>
 <p>
 <button (click)="updateProfile()">Update Profile</button>
 </p>

 <p>
 Form Status: {{ profileForm.status }}
 </p>
</form>

js

import { Component, OnInit } from '@angular/core';
import {FormControl, FormGroup, FormBuilder, Validators, FormArray} from '@angular/forms';

@Component({
 selector: 'app-profile-editor',
 templateUrl: './profile-editor.component.html',
 styleUrls: ['./profile-editor.component.css']
})
export class ProfileEditorComponent implements OnInit {
 profileForm = this.fb.group({
 firstName: ['张', Validators.required],
 lastName: ['以'],
 address: this.fb.group({
  street: [''],
  city: [''],
  state: [''],
  zip: ['']
 }),
 aliases: this.fb.array([
  this.fb.control('')
 ])
 });
 constructor(private fb: FormBuilder) {

 }

 ngOnInit() {
 }

 onSubmit () {
 console.warn(this.profileForm.value);
 }
 
 updateProfile() {
 this.profileForm.patchValue({
  firstName: 'Nancy',
  address: {
  street: '123 Drew Street'
  }
 });
 }
 get aliases () {
 return this.profileForm.get('aliases') as FormArray;
 }
 addAlias() {
 this.aliases.push(this.fb.control(''));
 }
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
Jquery 动态添加按钮实现代码
May 06 Javascript
javascript实现简单的Map示例介绍
Dec 23 Javascript
javascript客户端遍历控件与获取父容器对象示例代码
Jan 06 Javascript
鼠标移到图片上变大显示而不是放大镜效果
Jun 15 Javascript
Iframe实现跨浏览器自适应高度解决方法
Sep 02 Javascript
javascript结合fileReader 实现上传图片
Jan 30 Javascript
js中日期的加减法
May 06 Javascript
JavaScript获取浏览器信息的方法
Nov 20 Javascript
Vue实现的父组件向子组件传值功能示例
Jan 19 Javascript
Vue源码之关于vm.$delete()/Vue.use()内部原理详解
May 01 Javascript
vue-router二级导航切换路由及高亮显示的实现方法
Jul 10 Javascript
手把手教你从零开始react+antd搭建项目
Jun 03 Javascript
JS原生带缩略图的图片切换效果
Oct 10 #Javascript
js实现前面自动补全位数的方法
Oct 10 #Javascript
Egg.js 中 AJax 上传文件获取参数的方法
Oct 10 #Javascript
轻量级富文本编辑器wangEditor结合vue使用方法示例
Oct 10 #Javascript
解决eclipse中没有js代码提示的问题
Oct 10 #Javascript
js实现同一个页面,多个enter事件绑定的示例
Oct 10 #Javascript
在React项目中使用Eslint代码检查工具及常见问题
Oct 10 #Javascript
You might like
在PHP3中实现SESSION的功能(一)
2006/10/09 PHP
dede3.1分页文字采集过滤规则详说(图文教程)续四
2007/04/03 PHP
php图片验证码代码
2008/03/27 PHP
php获取某个目录大小的代码
2008/09/10 PHP
初识通用数据库操作类――前端easyui-datagrid,form(php)
2015/07/31 PHP
PHP实现将上传图片自动缩放到指定分辨率,并保持清晰度封装类示例
2019/06/17 PHP
JavaScript 模拟类机制及私有变量的方法及思路
2013/07/10 Javascript
jQuery圆形统计图开发实例
2015/01/04 Javascript
JQuery操作元素的css样式
2015/03/09 Javascript
js数组依据下标删除元素
2015/04/14 Javascript
分享9点个人认为比较重要的javascript 编程技巧
2015/04/27 Javascript
Node.js+Express配置入门教程
2016/05/19 Javascript
基于BootStrap环境写jQuery tabs插件
2016/07/12 Javascript
Javascript中apply、call、bind的巧妙使用
2016/08/18 Javascript
微信小程序 欢迎页面的制作(源码下载)
2017/01/09 Javascript
ES6字符串模板,剩余参数,默认参数功能与用法示例
2017/04/06 Javascript
JavaScript无操作后屏保功能的实现方法
2017/07/04 Javascript
解决vue this.$forceUpdate() 处理页面刷新问题(v-for循环值刷新等)
2018/07/26 Javascript
Vue与React的区别和优势对比
2020/12/18 Vue.js
[54:43]DOTA2-DPC中国联赛 正赛 CDEC vs Dynasty BO3 第一场 2月22日
2021/03/11 DOTA
详解Python中的多线程编程
2015/04/09 Python
python抓取多种类型的页面方法实例
2019/11/20 Python
基于Python测试程序是否有错误
2020/05/16 Python
基于python实现模拟数据结构模型
2020/06/12 Python
python 多进程和协程配合使用写入数据
2020/10/30 Python
整理HTML5的一些新特性与Canvas的常用属性
2016/01/29 HTML / CSS
美国巧克力喷泉品牌:Sephra
2019/05/05 全球购物
Spotahome意大利:公寓和房间出租
2020/02/21 全球购物
static函数与普通函数有什么区别
2015/12/25 面试题
一套.net面试题及答案
2016/11/02 面试题
《忆江南》教学反思
2014/04/07 职场文书
大型活动组织方案
2014/05/10 职场文书
检讨书怎么写
2015/05/07 职场文书
感恩老师主题班会
2015/08/12 职场文书
PHP实现创建以太坊钱包转账等功能
2021/04/21 PHP
Python3.8官网文档之类的基础语法阅读
2021/09/04 Python