如何在 Angular 中使用反应表单

简介

Angel提供了两种处理表单的方式:模板驱动表单和反应型表单(也称为模型驱动表单)。模板驱动的表单是以角度处理表单的默认方式。对于模板驱动的表单,模板指令用于构建表单的内部表示形式。使用反应式窗体,您可以在Component类中构建自己的窗体表示形式。

<$>[备注] 注: 反应形式是以角2引入的。 <$>

以下是反应形式的一些优点:

在本文中,您将探索如何将反应式应用于一个示例角度应用程序。

前提条件

如果你想跟随这篇文章,你将需要:

这篇文章假设你对角度有一些基本的了解。

这篇文章还假设你是从一个新的角度项目构建的,这个项目是由@angular/cli生成的。您可以参考此post,如果您是角度CLI的入门。

本教程通过了Node v15.1.0、npmv6.14.8、@angular/corev11.0.0、@angular/formsv11.0.0验证。

第一步-设置项目

出于本教程的目的,您将从一个使用@angular/cli生成的默认角度项目进行构建。

1npx @angular/cli new angular-reactive-forms-example --style=css --routing=false --skip-tests

这将配置一个新的角度项目,将样式设置为),不布线,并跳过测试。

导航到新创建的项目目录:

1cd angular-reactive-forms-example

要使用反应式表单,您将使用Reactive FormsModule而不是FormsModule

在您的代码编辑器中打开app.mode.ts,添加Reactive FormsModule

 1[label src/app/app.module.ts]
 2import { BrowserModule } from '@angular/platform-browser';
 3import { NgModule } from '@angular/core';
 4import { ReactiveFormsModule } from '@angular/forms';
 5
 6import { AppComponent } from './app.component';
 7
 8@NgModule({
 9  declarations: [
10    AppComponent
11  ],
12  imports: [
13    BrowserModule,
14    ReactiveFormsModule,
15  ],
16  providers: [],
17  bootstrap: [AppComponent]
18})
19export class AppModule { }

此时,您应该有了一个带有Reactive FormsModule的新角度投影。

第二步-在组件模板中添加表单

对于反应式形式,逻辑完全在Component类中声明。

在代码编辑器中打开app.Component.html并添加以下代码行:

 1[label src/app/app.component.html]
 2<form [formGroup]="myForm" (ngSubmit)="onSubmit(myForm)">
 3  <div>
 4    <label>
 5      Name:
 6      <input formControlName="name" placeholder="Your name">
 7    </label>
 8  </div>
 9  <div>
10    <label>
11      Email:
12      <input formControlName="email" placeholder="Your email">
13    </label>
14  </div>
15  <div>
16    <label>
17      Message:
18      <input formControlName="message" placeholder="Your message">
19    </label>
20  </div>
21  <button type="submit">Send</button>
22</form>

这段代码将创建一个包含三个字段的表单:nameemailMessage。还将有一个标签为)方法。

<$>[备注] 注意: 如果您使用的是ANGLE 2.x,还需要加上以form开头的novaliate指令,因为ANGLE覆盖HTML5‘S验证。角度为4+时,会在后台自动添加novaliate。 <$>

让我们来分解一下:

  • formGroup:表单在Component类中将被视为FormGroup,因此formGroup指令允许为表单组命名。
  • ngSubmit:表单提交时会触发的事件。
  • formControlName:每个表单字段都应该有一个formControlName指令,该指令的值将是Component类中使用的名称。

此时,您应该有了一个新的角度项目,其中包含一个使用形状的构件样板。

第三步-构建组件类

接下来,在Component类中,您将在FormGroup中定义FormGroup和单独的`FormControl。

如果提供了一个值When_Newing_aFormControl,它将被用作该字段的初始值。

注意FormGroupFormControl名称是如何与模板中使用的名称相同的。还要注意如何在ngOnInit生命周期hook:]中初始化FormGroup

 1[label src/app/app.component.ts]
 2import { Component, OnInit } from '@angular/core';
 3import { FormControl, FormGroup } from '@angular/forms';
 4
 5@Component({
 6  selector: 'app-root',
 7  templateUrl: './app.component.html',
 8  styleUrls: ['./app.component.css']
 9})
10export class AppComponent implements OnInit {
11  myForm: FormGroup;
12
13  ngOnInit() {
14    this.myForm = new FormGroup({
15      name: new FormControl('Sammy'),
16      email: new FormControl(''),
17      message: new FormControl('')
18    });
19  }
20
21  onSubmit(form: FormGroup) {
22    console.log('Valid?', form.valid); // true or false
23    console.log('Name', form.value.name);
24    console.log('Email', form.value.email);
25    console.log('Message', form.value.message);
26  }
27}

就本教程而言,onSubmit方法实际上不会将提交的表单值传递给任何外部服务或服务器。它用于显示如何访问表单的有效性和FormControl值。

此时,您可以编译应用程序并在Web浏览器中打开它。输入nameemailMessage的值,然后点击[提交],控制台日志就会显示出来。

第四步-更新组件类使用FormBuilder

可以使用FormBuilder助手重写ngOnInit表单结构。这允许您放弃所有_Newing_of表单组和表单控件。

在代码编辑器中重新访问app.Component.ts,移除FormControl,并将FormGroup替换为FormBuilder

 1[label src/app/app.component.ts]
 2import { Component, OnInit } from '@angular/core';
 3import { FormBuilder, FormGroup } from '@angular/forms';
 4
 5@Component({
 6  selector: 'app-root',
 7  templateUrl: './app.component.html',
 8  styleUrls: ['./app.component.css']
 9})
10export class AppComponent implements OnInit {
11  myForm: FormGroup;
12
13  constructor(private fb: FormBuilder) {}
14
15  ngOnInit() {
16    this.myForm = this.fb.group({
17      name: 'Sammy',
18      email: '',
19      message: ''
20    });
21  }
22
23  onSubmit(form: FormGroup) {
24    console.log('Valid?', form.valid); // true or false
25    console.log('Name', form.value.name);
26    console.log('Email', form.value.email);
27    console.log('Message', form.value.message);
28  }
29}

这段带有FormBuilder的代码减少了用于创建FormGroup的样板代码量。

第五步-更新组件类使用Validators

Validators类添加到您的导入中,并使用数组而不是简单的字符串值来声明表单控件。

数组中的第一个值是初始表单值,第二个值供验证器使用。请注意如何通过将多个验证器包装到一个数组中来在同一个表单控件上使用它们。

RevisitReview您的代码编辑器中的app.Component.ts并添加Validators

 1[label src/app/app.component.ts]
 2import { Component, OnInit } from '@angular/core';
 3import { FormBuilder, FormGroup, Validators } from '@angular/forms';
 4
 5@Component({
 6  selector: 'app-root',
 7  templateUrl: './app.component.html',
 8  styleUrls: ['./app.component.css']
 9})
10export class AppComponent implements OnInit {
11  myForm: FormGroup;
12
13  constructor(private fb: FormBuilder) {}
14
15  ngOnInit() {
16    this.myForm = this.fb.group({
17      name: ['Sammy', Validators.required],
18      email: ['', [Validators.required, Validators.email]],
19      message: ['', [Validators.required, Validators.minLength(15)]],
20    });
21  }
22
23  onSubmit(form: FormGroup) {
24    console.log('Valid?', form.valid); // true or false
25    console.log('Name', form.value.name);
26    console.log('Email', form.value.email);
27    console.log('Message', form.value.message);
28  }
29}

此代码在nameemailMessage字段中添加required d。它还确保email值使用有效的电子邮件地址格式。它还确保Message值至少为15个字符。

如果这些表单要求中有任何一项未通过,则valid值将为False。如果所有这些表单要求都通过,则valid值将为true

Step 6-获取模板中的表单值和有效性

在模板中,可以访问每个FormControl的值和有效性,以及整个表单组的值和有效性。

如果表单值无效,请重新访问app.Component.html,并使用* ngIf向用户显示反馈消息:

 1[label src/app/app.component.html]
 2<form [formGroup]="myForm" (ngSubmit)="onSubmit(myForm)">
 3  <div>
 4    <label>
 5      Name:
 6      <input formControlName="name" placeholder="Your name">
 7    </label>
 8    <div *ngIf="myForm.get('name').invalid && (myForm.get('name').dirty || myForm.get('name').touched)">
 9      Please provide a name.
10    </div>
11  </div>
12  <div>
13    <label>
14      Email:
15      <input formControlName="email" placeholder="Your email">
16    </label>
17    <div *ngIf="myForm.get('email').invalid && (myForm.get('email').dirty || myForm.get('email').touched)">
18      Please provide a valid email address.
19    </div>
20  </div>
21  <div>
22    <label>
23      Message:
24      <input formControlName="message" placeholder="Your message">
25    </label>
26    <div *ngIf="myForm.get('message').invalid && (myForm.get('message').dirty || myForm.get('message').touched)">
27      Messages must be at least 15 characters long.
28    </div>
29  </div>
30  <button type="submit" [disabled]="myForm.invalid">Send</button>
31</form>

这段代码检查用户是否与字段(dirtyTouched)进行了交互。然后,如果该值没有通过验证要求,它将显示错误消息。在解决表单值的所有问题之前,发送 按钮也将被禁用。

有多种方法可以检索表单控件值。本例使用myForm.get(‘name’),相当于myForm.control s.name。可以使用.hasError(‘Required’).errors.quired来检索错误信息。

结论

在本文中,您探索了如何将反应式应用于一个示例角度应用程序。您使用FormControlFormGroupFormBuilderValidators构建了一个带验证的示例表单。有关其他功能,请参考官方documentation.

如果您想了解更多有关ANGLE的信息,请查看我们的ANGLE主题页面以获取练习和编程项目。

Published At
Categories with 技术
Tagged with
comments powered by Disqus