本篇文章带大家了解一下angular中的表单,聊聊响应式表单与模板驱动表单,介绍一下响应式表单怎么验证表单输入,希望对大家有所帮助!
|
本篇文章带大家了解一下angular中的表单,聊聊响应式表单与模板驱动表单,介绍一下响应式表单怎么验证表单输入,希望对大家有所帮助!
一、angular表单简介Angular 提供了两种不同的方法来通过表单处理用户输入: 1.1 响应式表单与模板驱动表单的差异
1.2 建立表单模型响应式表单和模板驱动型表单都会跟踪用户与之交互的表单输入元素和组件模型中的表单数据之间的值变更。这两种方法共享同一套底层 1.3 常用表单基础类响应式表单和模板驱动表单都建立在下列基础类之上。
二、 响应式表单响应式表单使用显式的、不可变的方式,管理表单在特定的时间点上的状态。对表单状态的每一次变更都会返回一个新的状态,这样可以在变化时维护模型的整体性。响应式表单是围绕 2.1 添加基础表单控件使用表单控件有三个步骤。
import { ReactiveFormsModule } from '@angular/forms';
@NgModule({
imports: [
// other imports ...
ReactiveFormsModule
],
})
export class AppModule { }
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('');
}可以用 FormControl 的构造函数
<label> Name: <input type="text" [formControl]="name"> </label> 2.2 显示表单控件的值你可以用下列方式显示它的值:
<label>
Name:
<input type="text" [formControl]="name">
</label>
<p>Value: {{ name.value }}</p> public name = new FormControl('test');
public testValueChange() {
this.name.valueChanges.subscribe({
next: value => {
console.log("name value is: " + value);
}
})
}2.3 替换表单控件的值响应式表单还有一些方法可以用 updateName() {
this.name.setValue('Nancy' + new Date().getTime());
}<p> <button (click)="updateName()">Update Name</button> </p> 2.4 把表单控件分组表单中通常会包含几个
要将表单组添加到此组件中,请执行以下步骤。
import { FormControl, FormGroup } from '@angular/forms';
profileForm = new FormGroup({
firstName: new FormControl(''),
lastName: new FormControl(''),
});
// 可以整个获取值
public onSubmit() {
// TODO: Use EventEmitter with form value
console.warn(this.profileForm.value);// {firstName: "", lastName: ""}
}
// 可以借助 valueChanges 整个可观察对象整个获取值
this.profileForm.valueChanges.subscribe( {
next: value => {
console.log("name value is: " + JSON.stringify(value)); // dashboard.component.ts:53 name value is: {"firstName":"dddd","lastName":"bb"}
}
})
// 可以通过后期单个控件单独获取值
this.profileForm.get('firstName').valueChanges.subscribe({
next: value => {
console.log("First Name is: " + value); // First Name is: aa
}ps: 这个 FormGroup 用对象的形式提供了它的模型值,这个值来自组中
<form [formGroup]="profileForm" (ngSubmit)="onSubmit()">
<label>
First Name:
<input type="text" formControlName="firstName">
</label>
<label>
Last Name:
<input type="text" formControlName="lastName">
</label>
<button type="submit" [disabled]="!profileForm.valid">Submit</button>
</form>2.5 创建嵌套的表单组表单组可以同时接受单个表单控件实例和其它表单组实例作为其子控件。这可以让复杂的表单模型更容易维护,并在逻辑上把它们分组到一起。
public profileForm = new FormGroup({
firstName: new FormControl(''),
lastName: new FormControl(''),
address: new FormGroup({
street: new FormControl(''),
city: new FormControl(''),
state: new FormControl(''),
zip: new FormControl('')
})
});
// 可以借助 valueChanges 整个可观察对象整个获取值
this.profileForm.valueChanges.subscribe( {
next: value => {
console.log("name value is: " + JSON.stringify(value));// name value is: {"firstName":"","lastName":"","address":{"street":"b","city":"","state":"","zip":""}}
}
});
// 可以通过后期单个控件单独获取值
this.profileForm.get('firstName').valueChanges.subscribe({
next: value => {
console.log("First Name is: " + value);
}
});
// 可以获取form组件某个form组的整个值
this.profileForm.get('address').valueChanges.subscribe(({
next: value => {
console.log('address value is: ' + JSON.stringify(value));// address value is: {"street":"b","city":"","state":"","zip":""}
}
}));
// 可以获取form组件某个form组的某个formcontrol实例的值
this.profileForm.get('address').get('street').valueChanges.subscribe(({
next: value => {
console.log('street value is: ' + value);// street value is: b
}
}));
<form [formGroup]="profileForm" (ngSubmit)="onSubmit()">
<label>
First Name:
<input type="text" formControlName="firstName">
</label>
<label>
Last Name:
<input type="text" formControlName="lastName">
</label>
<div formGroupName="address">
<h3>Address</h3>
<label>
Street:
<input type="text" formControlName="street">
</label>
<label>
City:
<input type="text" formControlName="city">
</label>
<label>
State:
<input type="text" formControlName="state">
</label>
<label>
Zip Code:
<input type="text" formControlName="zip">
</label>
</div>
<button type="submit" [disabled]="!profileForm.valid">Submit</button>
</form>2.6 更新部分数据模型当修改包含多个 FormGroup 实例的值时,你可能只希望更新模型中的一部分,而不是完全替换掉。 有两种更新模型值的方式:
public updateProfile() {
// profileForm 模型中只有 firstName 和 street 被修改了。注意,street 是在 address 属性的对象中被修改的。这种结构是必须的,因为 patchValue() 方法要针对模型的结构进行更新。patchValue() 只会更新表单模型中所定义的那些属性。
this.profileForm.patchValue({
firstName: 'Nancy' + new Date().getTime(),
address: {
street: '123 Drew Street' + new Date().getTime()
}
});
// ERROR Error: Must supply a value for form control with name: 'lastName'.
// setValue() 方法会严格遵循表单组的结构
this.profileForm.setValue({
firstName: 'Nancy' + new Date().getTime(),
address: {
street: '123 Drew Street' + new Date().getTime()
}
});
}2.7 创建动态表单FormArray 是 FormGroup 之外的另一个选择,用于管理任意数量的匿名控件。像 FormGroup 实例一样,你也可以往 FormArray 中动态插入和移除控件,并且 FormArray 实例的值和验证状态也是根据它的子控件计算得来的。 不过,你不需要为每个控件定义一个名字作为 key,因此,如果你事先不知道子控件的数量,这就是一个很好的选择。 要定义一个动态表单,请执行以下步骤。
import { FormControl, FormGroup, FormArray } from '@angular/forms';
public profileForm = new FormGroup({
firstName: new FormControl(''),
lastName: new FormControl(''),
address: new FormGroup({
street: new FormControl(''),
city: new FormControl(''),
state: new FormControl(''),
zip: new FormControl('')
}),
aliases: new FormArray([
new FormControl('1')
])
});
public aliases = (<FormArray>this.profileForm.get('aliases'));
public addAlias() {
(<FormArray>this.profileForm.get('aliases')).push(new FormControl('1'));
}
// 获取整个 formArray 的数据
this.profileForm.get('aliases').valueChanges.subscribe({
next: value => {
console.log('aliases values is: ' + JSON.stringify(value)); // aliases values is: ["1","3"]
}
});
// 获取 formArray 中单个 formControl 的数据
(<FormArray>this.profileForm.get('aliases')).controls[0].valueChanges.subscribe({
next: value => {
console.log('aliases[0] values is: ' + value); // aliases[0] values is: 0
}
})
<form [formGroup]="profileForm" (ngSubmit)="onSubmit()">
<label>
First Name:
<input type="text" formControlName="firstName">
</label>
<label>
Last Name:
<input type="text" formControlName="lastName">
</label>
<div formGroupName="address">
<h3>Address</h3>
<label>
Street:
<input type="text" formControlName="street">
</label>
<label>
City:
<input type="text" formControlName="city">
</label>
<label>
State:
<input type="text" formControlName="state">
</label>
<label>
Zip Code:
<input type="text" formControlName="zip">
</label>
</div>
<div formArrayName="aliases">
<h3>Aliases</h3> <button (click)="addAlias()">Add Alias</button>
<div *ngFor="let alias of aliases.controls; let i=index">
<!-- The repeated alias template -->
<label>
Alias:
<input type="text" [formControlName]="i">
</label>
</div>
</div>
</form>2.8 响应式表单 API 汇总
三、模板驱动表单在模板驱动表单中,表单模型是隐式的,而不是显式的。指令 NgModel 为指定的表单元素创建并管理一个 FormControl 实例。 import { Component } from '@angular/core';
@Component({
selector: 'app-template-favorite-color',
template: `
Favorite Color: <input type="text" [(ngModel)]="favoriteColor">
`
})
export class FavoriteColorComponent {
favoriteColor = '';
}四、响应式表单验证表单输入在组件类中 4.1 验证器(Validator)函数验证器函数可以是同步函数,也可以是异步函数。
出于性能方面的考虑,只有在所有同步验证器都通过之后,Angular 才会运行异步验证器。当每一个异步验证器都执行完之后,才会设置这些验证错误。 4.2 内置验证器函数在模板驱动表单中用作属性的那些内置验证器,比如 required 和 minlength,也都可以作为 Validators 类中的函数使用 public profileForm = new FormGroup({
firstName: new FormControl('', [
Validators.required
]),
});
this.profileForm.get('firstName').valueChanges.subscribe({
next: value => {
console.log("First Name is: " + value);
console.log(this.profileForm.get('firstName').errors);// { required: true } | null
}
}); <form [formGroup]="profileForm">
<label>
First Name:
<input type="text" formControlName="firstName">
<div *ngIf="firstName.errors?.required">
Name is required.
</div>
</label>
</form>4.3 定义自定义验证器内置的验证器并不是总能精确匹配应用中的用例,因此有时你需要创建一个自定义验证器。 public profileForm = new FormGroup({
firstName: new FormControl('', [
Validators.required,
this.forbiddenNameValidator(/bob/i)
])
});
public forbiddenNameValidator(nameRe: RegExp): ValidatorFn {
return (control: AbstractControl): {[key: string]: any} | null => {
const forbidden = nameRe.test(control.value);
return forbidden ? {forbiddenName: {value: control.value}} : null;
};
}
get firstName() { return this.profileForm.get('firstName'); }
this.profileForm.get('firstName').valueChanges.subscribe({
next: value => {
console.log("First Name is: " + value); // First Name is: bob
console.log(JSON.stringify(this.profileForm.get('firstName').errors));// {"forbiddenName":{"value":"bob"}} | null
}
});4.4 跨字段交叉验证跨字段交叉验证器是一种 下列交叉验证的例子说明了如何进行如下操作:
this.profileForm.valueChanges.subscribe( {
next: value => {
console.log(JSON.stringify(this.profileForm.errors));// {"identityRevealed":true} | null
}
});
public profileForm = new FormGroup({
firstName: new FormControl('', [
Validators.required,
]),
lastName: new FormControl(''),
}, { validators: this.identityRevealedValidator});
public identityRevealedValidator(control: FormGroup): ValidationErrors | null{
const firstName = control.get('firstName');
const lastName = control.get('lastName');
return firstName && lastName && firstName.value === lastName.value ? { identityRevealed: true } : null;
};4.5 创建异步验证器异步验证器实现了
4.6 触发某个formControlName let formControl = this.profileForm.get('firstName');
formControl.updateValueAndValidity();更多编程相关知识,请访问:编程视频!! 以上就是深入了解angular中的表单(响应式和模板驱动)的详细内容,更多请关注模板之家(www.mb5.com.cn)其它相关文章! |
