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 组件之旅(三):用 Ant 构建组件
Oct 28 Javascript
jQuery-ui中自动完成实现方法
Jun 10 Javascript
用JQuery实现表格隔行变色和突出显示当前行的代码
Feb 10 Javascript
js判断一个字符串是否包含一个子串的方法
Jan 26 Javascript
JS表的模拟方法
Feb 05 Javascript
基于JS分页控件实现简单美观仿淘宝分页按钮效果
Nov 07 Javascript
原生js实现商品放大镜效果
Jan 12 Javascript
使用Math.max,Math.min获取数组中的最值实例
Apr 25 Javascript
angularjs2中父子组件的数据传递的实例代码
Jul 05 Javascript
vue2.0父子组件间传递数据的方法
Aug 16 Javascript
微信小程序之高德地图多点路线规划过程示例详解
Jan 18 Javascript
JavaScript canvas实现流星特效
May 20 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
Admin generator, filters and I18n
2011/10/06 PHP
php中配置文件操作 如config.php文件的读取修改等操作
2012/07/07 PHP
php基于mcrypt的加密解密实例
2014/10/27 PHP
PHP7扩展开发教程之Hello World实现方法示例
2017/08/03 PHP
javascript 循环读取JSON数据的代码
2010/07/17 Javascript
Wordpress ThickBox 添加“查看原图”效果代码
2010/12/11 Javascript
始终在屏幕中间显示Div的代码(css+js)
2011/03/10 Javascript
19个很有用的 JavaScript库推荐
2011/06/27 Javascript
javascript时间自动刷新实现原理与步骤
2013/01/06 Javascript
javascript自启动函数的问题探讨
2013/10/05 Javascript
javascript实现回到顶部特效
2015/05/06 Javascript
node-http-proxy修改响应结果实例代码
2016/06/06 Javascript
javascript设计模式Constructor(构造器)模式
2016/08/19 Javascript
JavaScript使用键盘输入控制实现数字验证功能
2016/08/19 Javascript
jquery滚动条插件(可以自定义)
2016/12/11 Javascript
JavaScript 数据类型详解
2017/03/13 Javascript
JavaScript数据结构中栈的应用之表达式求值问题详解
2017/04/11 Javascript
详解Vue2 SSR 缓存 Api 数据
2017/11/20 Javascript
vue 点击按钮实现动态挂载子组件的方法
2018/09/07 Javascript
详解Python list 与 NumPy.ndarry 切片之间的对比
2017/07/24 Python
利用python批量修改word文件名的方法示例
2017/10/17 Python
python实现机器人行走效果
2018/01/29 Python
Python实现的knn算法示例
2018/06/14 Python
Django Rest framework之认证的实现代码
2018/12/17 Python
python实现抽奖小程序
2020/04/15 Python
解决Python Matplotlib绘图数据点位置错乱问题
2020/05/16 Python
python logging 重复写日志问题解决办法详解
2020/08/04 Python
Python爬虫后获取重定向url的两种方法
2021/01/19 Python
python 基于UDP协议套接字通信的实现
2021/01/22 Python
惠而浦美国官网:Whirlpool.com
2021/01/19 全球购物
Discard Protocol抛弃协议的作用是什么
2015/10/10 面试题
出口公司经理求职简历中的自我评价
2013/10/13 职场文书
银行工作检查书范文
2014/01/31 职场文书
人力资源管理专业自荐书
2014/07/07 职场文书
实习单位意见
2015/06/04 职场文书
详解 TypeScript 枚举类型
2021/11/02 Javascript