
Angular FormGroup跟踪一组FormControl实例的值和有效性状态。ReactiveFormsModule启用了FormGroup。FormGroup与FormControl和FormArray一起使用。FormGroup的作用是跟踪表单控件的值和验证状态。
Angular 14 FormGroup
Angular FormGroup 将每个子FormControl的值聚集到一个对象中,每个控件的名字是关键。FormGroup通过减少其子控件的状态值来计算其状态。例如,如果组中的一个控件是无效的,整个组就会变成无效的。
FormGroup是Angular中用来定义表单的三个基本构件之一,另外还有FormControl和FormArray。
当实例化FormGroup时,传入子控件的集合作为第一个参数。每个子控件的关键是注册该控件的名称。
在这个例子中,我们将看到如何实例化Angular FormGroup并设置和访问FormGroup中的值。我们还将验证该表单。
让我们了解一下我们将在本例中使用的angular表单类和指令。
FormControl:
FormControl是一个跟踪FormControl的值和验证状态的类。
FormGroup:
FormGroup是一个跟踪一组FormControl的值和有效性状态的类。
FormArray:
FormArray是一个跟踪FormControl、FormGroup和 FormArray数组的值和有效性状态的类。
FormControlName:
FormControlName是一个指令,它将现有的FormGroup中的FormControl按名称同步到一个表单控件。
FormGroupDirective:
FormGroupDirective是一个指令,将现有的FormGroup绑定到一个DOM元素。
FormGroupName:
FormGroupName是一个指令,用于将一个嵌套的FormGroup同步到一个DOM元素。
FormArrayName:
FormArrayName是一条指令,用于将一个嵌套的FormArray同步到一个DOM元素。
例子
让我们回到实践中去,创建一个新的Angular项目。
正如前面所讨论的,我们需要导入ReactiveFormsModule来处理FormGroup。
所以,在app.module.ts 文件中导入ReactiveFormsModule。
// app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { ReactiveFormsModule } from '@angular/forms';
import { AppComponent } from './app.component';
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
ReactiveFormsModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
下一步是在app.component.ts 文件中编写以下代码。
// app.component.ts
import { Component } from '@angular/core';
import { FormControl, FormGroup, Validators } from '@angular/forms';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
mandoForm = new FormGroup({
name: new FormControl(),
series: new FormControl('The Mandalorian')
});
onFormSubmit(): void {
console.log('Name:' + this.mandoForm.get('name').value);
console.log('Series:' + this.mandoForm.get('series').value);
}
}
我们已经在app.component.ts 文件中导入了FormControl和Validators 类,并创建了一个FormGroup的实例,由FormControl实例的名称 和系列组成。
当用户提交表单数据时,onFormSubmit()函数将被触发。将以下代码写进app.component.html文件。
<form [formGroup]="mandoForm" (ngSubmit)="onFormSubmit()">
Name: <input formControlName="name" placeholder="Enter Name">
Series: <input formControlName="series" placeholder="Enter Series">
<button type="submit">Submit</button>
</form>
保存该文件并使用以下命令启动Angular的开发服务器。
ng serve -o
在输出中,你可以看到两个文本框,其中一个充满了值,当你提交表单时,你会看到这些文本框的值被记录在浏览器的控制台中。
表格组 setValue() 和 patchValue()
**setValue()和patchValue()**是用来在运行时给FormGroup实例设置值的。
它们之间的主要区别是,当我们使用setValue()时,我们必须设置我们的FormGroup中的所有表单控件,而当我们使用patchValue()时,选定的表单控件可以被设置。
如果我们使用setValue(),但没有设置我们的表单组中的所有表单控件,它将抛出一个错误。
如果我们使用patchValue(),就没有必要在我们的表单组中设置所有的表单控件。
让我们通过下面的例子来理解。
在app.component.ts 文件中加入以下代码。
// app.component.ts
import { Component } from '@angular/core';
import { FormControl, FormGroup, Validators } from '@angular/forms';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
mandoForm = new FormGroup({
name: new FormControl('Starwars'),
series: new FormControl('C3PO')
});
onReset(): void {
this.mandoForm.setValue({name: 'Padro Pascal', series: 'The Mandalorian' });
}
onPatch(): void {
this.mandoForm.patchValue({ name: 'Padro Pascal' });
}
onFormSubmit(): void {
console.log('Name:' + this.mandoForm.get('name').value);
console.log('Series:' + this.mandoForm.get('series').value);
}
}
在上面的代码中,我们已经用两个表单控件初始化了mandoForm表单组。
然后我们定义了三个函数来重置和修补表单控件的值。
在表单组中使用setValue()
正如我前面提到的,setValue()需要所有的表单控件值,如果缺少一个,它将抛出一个错误,如下所示。
AppComponent.html:4 ERROR 错误。必须为名称为 "系列 "的表单控件提供一个值。
at forms.js:4504
at forms.js:4405
at Array.forEach (<anonymous>)
at FormGroup.\_forEachChild (forms.js:4401)
at FormGroup.\_checkAllValuesPresent (forms.js:4497)
at FormGroup.setValue (forms.js:4215)
at AppComponent.onReset (app.component.ts:15)
at Object.eval \[as handleEvent\] (AppComponent.html:4)
at handleEvent (core.js:34789)
at callWithDebugContext (core.js:36407)
View\_AppComponent\_0 @ AppComponent.html:4
proxyClass @ compiler.js:19257
logError @ core.js:36342
handleError @ core.js:7239
dispatchEvent @ core.js:22537
(anonymous) @ core.js:33721
(anonymous) @ platform-browser.js:1789
invokeTask @ zone-evergreen.js:391
onInvokeTask @ core.js:30885
invokeTask @ zone-evergreen.js:390
runTask @ zone-evergreen.js:168
invokeTask @ zone-evergreen.js:465
invokeTask @ zone-evergreen.js:1603
globalZoneAwareCallback @ zone-evergreen.js:1629
AppComponent.html:4 ERROR CONTEXT DebugContext\_ {view:{...}, nodeIndex:19, nodeDef: {...}, elDef: {...}, elView:{...}}
所以,为了避免这个错误,我们必须传递所有的表单控件。
使用patchValue()
当我们使用patchValue()时,没有必要提及所有表单控件。
onPatch(): void {
this.mandoForm.patchValue({ name: 'Padro Pascal' });
}
我们没有传递系列表单控件。
现在,在app.component.html 文件中写下以下代码。
<!-- app.component.html -->
<form [formGroup]="mandoForm" (ngSubmit)="onFormSubmit()">
Name: <input formControlName="name" placeholder="Enter Name">
Series: <input formControlName="series" placeholder="Enter Series">
<button (click) = "onReset()">Reset</button>
<button (click) = "onPatch()">Patch</button>
<button type="submit">Submit</button>
</form>
现在,你可以重置或修补表单控件的值。
表单组获取值
FormGroup是一个表单控件的集合。所以,我们可以使用下面的方法获得表单控件名称的值。
this.mandoForm.get('name').value
在上面的例子中,我们已经在**onFormSubmit()**方法里面使用了这个方法。
onFormSubmit(): void {
console.log('Name:' + this.mandoForm.get('name').value);
console.log('Series:' + this.mandoForm.get('series').value);
}
Angular中的FormGroup reset()。
我们可以通过调用FormGroup实例的reset()方法来重置整个表单。
// app.component.ts
OnCompleteReset() {
this.mandoForm.reset();
}
你可以定义你的方法并在FormGroup实例上调用reset() 方法。它将重置表单的值。你需要通过点击按钮或其他事件来调用这个方法。
如果我们想用一些默认值来重置表单,那么就用表单控件的名称来指定默认值。
// app.component.ts
OnCompleteReset() {
this.mandoForm.reset({
name: 'EdwardSnowden',
series: 'CIA'
});
}
表单组 valueChanges() 和 statusChanges()
我们可以跟踪表单控件的值变化和状态变化;我们需要使用subscribe()方法来监听它们。请看下面的代码。
// app.component.ts
import { Component, AfterViewInit } from '@angular/core';
import { FormControl, FormGroup } from '@angular/forms';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements AfterViewInit {
usrNameChanges: string;
usrNameStatus: string;
mandoForm = new FormGroup({
name: new FormControl('Starwars'),
series: new FormControl('C3PO')
});
ngAfterViewInit(): void {
this.mandoForm.get('name').valueChanges.subscribe(data => this.usrNameChanges = data);
this.mandoForm.get('name').statusChanges.subscribe(data => this.usrNameStatus = data);
}
}
我们已经实现了AfterViewInit接口的ngAfterViewInit()生命周期 方法。
因此,当用户改变文本框的值时,subscribe()方法会进行监听,我们可以获得这些文本框值的最新数据。
在html视图里面,我们可以检查这些值,如果这个名字改变了,我们就会显示这些值。例如,请看下面的app.component.html 文件的代码。
<!-- app.component.html -->
<form [formGroup]="mandoForm">
Name: <input formControlName="name" placeholder="Enter Name">
Series: <input formControlName="series" placeholder="Enter Series">
</form>
<p *ngIf="usrNameChanges">Name: <b>{{usrNameChanges}}</b> </p>
<p *ngIf="usrNameStatus">Name Status: <b>{{usrNameStatus}}</b> </p>
请看输出。
Angular表单组验证
我们可以使用Validators类对FormGroup中的表单控件进行验证。我们可以用它来启用表单控件的验证,如下图所示。
// app.component.ts
import { Component } from '@angular/core';
import { FormControl, FormGroup, Validators } from '@angular/forms';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
mandoForm = new FormGroup({
name: new FormControl('', Validators.required),
series: new FormControl('', Validators.required)
});
get name(): any {
return this.mandoForm.get('name');
}
onFormSubmit(): void {
console.log('Name:' + this.mandoForm.get('name').value);
console.log('Series:' + this.mandoForm.get('series').value);
}
}
为了检查表单控件的有效性,我们为表单控件写了以下方法,如下所示。
get name(): any {
return this.mandoForm.get('name');
}
现在在HTML模板中,我们可以以userName.invalid的形式访问有效性状态。我们也可以使用FormGroup的一个实例直接获得有效性状态。
mandoForm.get('series').invalid
最终用于验证的HTML代码如下。
<form [formGroup]="mandoForm" (ngSubmit)="onFormSubmit()">
<div>
Name: <input formControlName="name" placeholder="Enter Name">
<label *ngIf="name.invalid" [ngClass] = "'error'"> Name is required with 10 max character. </label>
</div>
<div>
Series: <input formControlName="series" placeholder="Enter Series">
<label *ngIf="mandoForm.get('series').invalid" [ngClass] = "'error'"> Series is required. </label>
</div>
<div>
<button type="submit">Submit</button>
</div>
</form>
请看输出。
总结
简而言之,FormGroup是一个FormControls的集合。它跟踪所有的FormControl实例的值。
我们已经看到了如何在Angular中使用FormGroup与FormControl、Validators、以及不同的方法和属性。
本教程到此结束。

