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 相关文章推荐
JavaScript iframe的相互操作浅析
Oct 14 Javascript
图片上传判断及预览脚本的效果实例
Aug 07 Javascript
js实现日历可获得指定日期周数及星期几示例分享(js获取星期几)
Mar 14 Javascript
javascript中DOM复选框选择用法实例
May 14 Javascript
JavaScript中的lastIndexOf()方法使用详解
Jun 06 Javascript
Vuejs第十篇之vuejs父子组件通信
Sep 06 Javascript
IE8利用自带的setCapture和releaseCapture解决iframe的拖拽事件方法
Oct 25 Javascript
详解Html a标签中href和onclick用法、区别、优先级别
Jan 16 Javascript
详谈for循环里面的break和continue语句
Jul 20 Javascript
利用node.js爬取指定排名网站的JS引用库详解
Jul 25 Javascript
使用百度地图实现地图网格的示例
Feb 06 Javascript
jQuery.validate.js表单验证插件的使用代码详解
Oct 22 jQuery
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
使用php+Ajax实现唯一校验实现代码[简单应用]
2011/11/29 PHP
linux下安装php的memcached客户端
2014/08/03 PHP
PHP四舍五入、取整、round函数使用示例
2015/02/06 PHP
php中foreach结合curl实现多线程的方法分析
2016/09/22 PHP
Yii2.0实现生成二维码功能实例
2017/10/24 PHP
用js实现下载远程文件并保存在本地的脚本
2008/05/06 Javascript
jQuery一步一步实现跨浏览器的可编辑表格,支持IE、Firefox、Safari、Chrome、Opera
2009/08/28 Javascript
漂亮的jquery提示效果(仿腾讯弹出层)
2013/02/05 Javascript
鼠标拖拽移动子窗体的JS实现
2014/02/25 Javascript
javascript中错误使用var造成undefined
2016/03/31 Javascript
关于JSON.parse(),JSON.stringify(),jQuery.parseJSON()的用法
2016/06/30 Javascript
JS实现类似百叶窗下拉菜单效果
2016/12/30 Javascript
JavaScript体验异步更好的解决办法
2018/01/08 Javascript
[00:52]玛尔斯技能全介绍
2019/03/06 DOTA
在Python中进行自动化单元测试的教程
2015/04/15 Python
python用reduce和map把字符串转为数字的方法
2016/12/19 Python
Python使用 Beanstalkd 做异步任务处理的方法
2018/04/24 Python
Python高斯消除矩阵
2019/01/02 Python
django的ORM模型的实现原理
2019/03/04 Python
python处理大日志文件
2019/07/23 Python
pyMySQL SQL语句传参问题,单个参数或多个参数说明
2020/06/06 Python
完美解决keras 读取多个hdf5文件进行训练的问题
2020/07/01 Python
python中slice参数过长的处理方法及实例
2020/12/15 Python
TALLY WEiJL法国网上商店:服装、时装及配饰
2019/08/31 全球购物
J2EE是技术还是平台还是框架
2016/08/14 面试题
护士毕业生自我鉴定
2014/02/08 职场文书
网络工程师职业规划
2014/02/10 职场文书
学历公证书范本
2014/04/09 职场文书
情感电台广播稿
2015/08/18 职场文书
2016计算机专业毕业生自荐信
2016/01/28 职场文书
python绘制箱型图
2021/04/27 Python
如何解决.cuda()加载用时很长的问题
2021/05/24 Python
redis使用不当导致应用卡死bug的过程解析
2021/07/01 Redis
SQL SERVER存储过程用法详解
2022/02/24 SQL Server
「我的青春恋爱物语果然有问题。-妄言录-」第20卷封面公开
2022/03/21 日漫
JavaScript架构localStorage特殊场景下二次封装操作
2022/06/21 Javascript