Angular 14 FormGroup:完整指南

2,646 阅读6分钟

Angular 8 FormGroup Example Tutorial From Scratch

Angular FormGroup跟踪一组FormControl实例的值和有效性状态。ReactiveFormsModule启用了FormGroup。FormGroup与FormControl和FormArray一起使用。FormGroup的作用是跟踪表单控件的值和验证状态。

Angular 14 FormGroup

Angular FormGroup 将每个子FormControl的值聚集到一个对象中,每个控件的名字是关键。FormGroup通过减少其子控件的状态值来计算其状态。例如,如果组中的一个控件是无效的,整个组就会变成无效的。

FormGroup是Angular中用来定义表单的三个基本构件之一,另外还有FormControlFormArray

当实例化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 8 FormGroup Example

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>

请看输出。

Angular 8 FormGroup Validation

总结

简而言之,FormGroup是一个FormControls的集合。它跟踪所有的FormControl实例的值。

我们已经看到了如何在Angular中使用FormGroup与FormControl、Validators、以及不同的方法和属性。

本教程到此结束。