Angular学习笔记之-11.表单
Angular 表单简介
响应式表单和模板驱动表单以不同的方式处理和管理表单数据。每种方法都有各自的优点。
1.响应式表单提供对底层表单对象模型直接、显式的访问。它们与模板驱动表单相比,更加健壮:它们的可扩展性、可复用性和可测试性都更高。如果表单是你的应用程序的关键部分,或者你已经在使用响应式表单来构建应用,那就使用响应式表单。
2.模板驱动表单依赖模板中的指令来创建和操作底层的对象模型。它们对于向应用添加一个简单的表单非常有用,比如电子邮件列表注册表单。它们很容易添加到应用中,但在扩展性方面不如响应式表单。如果你有可以只在模板中管理的非常基本的表单需求和逻辑,那么模板驱动表单就很合适。
响应式表单
对于响应式表单,你可以直接在组件类中定义表单模型。[formControl] 指令会通过内部值访问器来把显式创建的 FormControl 实例与视图中的特定表单元素联系起来。
import { Component } from '@angular/core';
import { FormControl } from '@angular/forms';
@Component({
selector: 'app-forms-reactive',
template:
`
<h1>app-forms-reactive</h1>
Favorite Color: <input type="text" [formControl]="favoriteColorControl">
`,
})
export class FormsReactiveComponent {
favoriteColorControl = new FormControl('');
}
建立模板驱动表单
在模板驱动表单中,表单模型是隐式的,而不是显式的。指令 NgModel 为指定的表单元素创建并管理一个 FormControl 实例。
import { Component } from '@angular/core';
@Component({
selector: 'app-forms-template-driven',
template: `
<h1>app-forms-template-driven</h1>
Favorite Color: <input type="text" [(ngModel)]="favoriteColor" />
`,
})
export class FormsTemplateDrivenComponent {
_favoriteColor = '2222';
get favoriteColor() {
return this._favoriteColor;
}
set favoriteColor(value) {
console.log('value:', value);
this._favoriteColor = value;
}
}
响应式表单详解
添加基础表单控件
使用表单控件有三个步骤。
1.在你的应用中注册响应式表单模块。该模块声明了一些你要用在响应式表单中的指令。
2.生成一个新的 FormControl 实例,并把它保存在组件中。
3.在模板中注册这个 FormControl
代码示例
/* name-editor.component.ts */
import { Component, OnInit } 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 implements OnInit {
name = new FormControl('kwok');
ngOnInit(): void {
/* 监听值得变化 */
this.name.valueChanges.subscribe((res) => {
console.log('name-change:', res);
});
}
/* 替换表单控件的值 */
updateName() {
this.name.setValue('Nancy');
}
}
<!-- name-editor.component.html -->
<label>
Name:
<input type="text" [formControl]="name" />
</label>
<!-- 显示表单控件的值 -->
<p>Value: {{ name.value }}</p>
<p>
<button (click)="updateName()">Update Name</button>
</p>
把表单控件分组
要将表单组添加到此组件中,请执行以下步骤。
1.创建一个 FormGroup 实例。
2.把这个 FormGroup 模型关联到视图。
3.保存表单数据。
代码示例
/* profile-editor.component.ts */
import { FormGroup, FormControl,FormBuilder } from '@angular/forms';
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-profile-editor',
templateUrl: './profile-editor.component.html',
styleUrls: ['./profile-editor.component.css'],
})
export class ProfileEditorComponent implements OnInit {
profileForm = new FormGroup({
firstName: new FormControl(''),
lastName: new FormControl(''),
/* 创建嵌套的表单组 */
address: new FormGroup({
street: new FormControl(''),
city: new FormControl(''),
state: new FormControl(''),
zip: new FormControl(''),
}),
});
constructor(private fb: FormBuilder) { }
ngOnInit(): void {
this.profileForm.valueChanges.subscribe((res) => {
console.log('res:', res);
});
}
onSubmit() {
console.log('this.profileForm:', this.profileForm.value);
}
/* 更新部分数据模型 */
updateProfile() {
// this.profileForm.patchValue({
// firstName: 'Nancy',
// address: {
// street: '123 Drew Street',
// },
// });
this.profileForm.setValue({
firstName: 'Nancy',
lastName: '',
address: {
street: '123 Drew Street',
city: '',
state: '',
zip: '',
},
});
}
}
<!-- profile-editor.component.html -->
<form [formGroup]="profileForm">
<label>
firstName:
<input type="text" formControlName="firstName" />
</label>
<br />
<label>
lastName:
<input type="text" formControlName="lastName" />
</label>
<br />
<form formGroupName="address">
<label>
street:
<input type="text" formControlName="street" />
</label>
<br />
<label>
city:
<input type="text" formControlName="city" />
</label>
<br />
<label>
state:
<input type="text" formControlName="state" />
</label>
<br />
<label>
zip:
<input type="text" formControlName="zip" />
</label>
<br />
</form>
</form>
<button type="submit" [disabled]="!profileForm.valid" (click)="onSubmit()">
Submit
</button>
<p>
<button (click)="updateProfile()">Update Profile</button>
</p>
<p>Value: {{ profileForm.value | json }}</p>
使用 FormBuilder 服务生成控件
通过下列步骤可以利用这项服务。
1.导入 FormBuilder 类。
2.注入这个 FormBuilder 服务。
3.生成表单内容
代码示例
/* profile-editor.component.ts */
import {FormBuilder } from '@angular/forms';
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-profile-editor',
templateUrl: './profile-editor.component.html',
styleUrls: ['./profile-editor.component.css'],
})
export class ProfileEditorFormBuilderComponent implements OnInit {
profileForm = this.fb.group({
firstName: [''],
lastName: [''],
address: this.fb.group({
street: [''],
city: [''],
state: [''],
zip: ['']
}),
});
constructor(private fb: FormBuilder) { }
ngOnInit(): void {
this.profileForm.valueChanges.subscribe((res) => {
console.log('res:', res);
});
}
onSubmit() {
console.log('this.profileForm:', this.profileForm.value);
}
updateProfile() {
// this.profileForm.patchValue({
// firstName: 'Nancy',
// address: {
// street: '123 Drew Street',
// },
// });
this.profileForm.setValue({
firstName: 'Nancy',
lastName: '',
address: {
street: '123 Drew Street',
city: '',
state: '',
zip: '',
},
});
}
}
<!-- profile-editor.component.html -->
<form [formGroup]="profileForm">
<label>
firstName:
<input type="text" formControlName="firstName" />
</label>
<br />
<label>
lastName:
<input type="text" formControlName="lastName" />
</label>
<br />
<form formGroupName="address">
<label>
street:
<input type="text" formControlName="street" />
</label>
<br />
<label>
city:
<input type="text" formControlName="city" />
</label>
<br />
<label>
state:
<input type="text" formControlName="state" />
</label>
<br />
<label>
zip:
<input type="text" formControlName="zip" />
</label>
<br />
</form>
</form>
<button type="submit" [disabled]="!profileForm.valid" (click)="onSubmit()">
Submit
</button>
<p>
<button (click)="updateProfile()">Update Profile</button>
</p>
<p>Value: {{ profileForm.value | json }}</p>
验证表单输入
使用下列步骤添加表单验证。
1.在表单组件中导入一个验证器函数。
2.把这个验证器添加到表单中的相应字段。
3.添加逻辑来处理验证状态。
代码示例
/* profile-editor.component.ts */
import { FormBuilder, Validators } from '@angular/forms';
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-profile-editor',
templateUrl: './profile-editor.component.html',
styleUrls: ['./profile-editor.component.css'],
})
export class ProfileEditorValidatingComponent implements OnInit {
profileForm = this.fb.group({
firstName: ['', Validators.required],
lastName: [''],
address: this.fb.group({
street: [''],
city: [''],
state: [''],
zip: [''],
}),
});
constructor(private fb: FormBuilder) {}
ngOnInit(): void {
this.profileForm.valueChanges.subscribe((res) => {
console.log('res:', res);
});
}
onSubmit() {
console.log('this.profileForm:', this.profileForm.value);
}
updateProfile() {
this.profileForm.patchValue({
firstName: 'Nancy',
address: {
street: '123 Drew Street',
},
});
}
}
<!-- profile-editor.component.html -->
<form [formGroup]="profileForm">
<label>
firstName:
<input type="text" formControlName="firstName" />
</label>
<br />
<label>
lastName:
<input type="text" formControlName="lastName" />
</label>
<br />
<form formGroupName="address">
<label>
street:
<input type="text" formControlName="street" />
</label>
<br />
<label>
city:
<input type="text" formControlName="city" />
</label>
<br />
<label>
state:
<input type="text" formControlName="state" />
</label>
<br />
<label>
zip:
<input type="text" formControlName="zip" />
</label>
<br />
</form>
</form>
<button type="submit" [disabled]="!profileForm.valid" (click)="onSubmit()">
Submit
</button>
<p>
<button (click)="updateProfile()">Update Profile</button>
</p>
<p>Value: {{ profileForm.value | json }}</p>
<p>Form Status: {{ profileForm.status }}</p>
创建动态表单
使用下列步骤添加表单验证。
1.导入 FormArray 类。
2.定义一个 FormArray 控件。
3.使用 getter 方法访问 FormArray 控件。
4.在模板中显示这个表单数组。
代码示例
/* profile-editor.component.ts */
import { FormBuilder, Validators, FormArray } from '@angular/forms';
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-profile-editor',
templateUrl: './profile-editor.component.html',
styleUrls: ['./profile-editor.component.css'],
})
export class ProfileEditorDynamicComponent 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('')
])
});
get aliases() {
return this.profileForm.get('aliases') as FormArray;
}
constructor(private fb: FormBuilder) {}
ngOnInit(): void {
this.profileForm.valueChanges.subscribe((res) => {
console.log('res:', res);
});
}
onSubmit() {
console.log('this.profileForm:', this.profileForm.value);
}
updateProfile() {
this.profileForm.patchValue({
firstName: 'Nancy',
address: {
street: '123 Drew Street',
},
});
}
addAlias() {
this.aliases.push(this.fb.control(''));
}
}
<!-- profile-editor.component.html -->
<form [formGroup]="profileForm">
<label>
firstName:
<input type="text" formControlName="firstName" />
</label>
<br />
<label>
lastName:
<input type="text" formControlName="lastName" />
</label>
<br />
<form formGroupName="address">
<label>
street:
<input type="text" formControlName="street" />
</label>
<br />
<label>
city:
<input type="text" formControlName="city" />
</label>
<br />
<label>
state:
<input type="text" formControlName="state" />
</label>
<br />
<label>
zip:
<input type="text" formControlName="zip" />
</label>
<br />
</form>
<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>
<button type="submit" [disabled]="!profileForm.valid" (click)="onSubmit()">
Submit
</button>
<p>
<button (click)="updateProfile()">Update Profile</button>
</p>
<p>Value: {{ profileForm.value | json }}</p>
<p>Form Status: {{ profileForm.status }}</p>