Angular 2 响应式表单与模板表单

Angular 2 Reactive Forms vs Template Forms

我们正在开始一个新的 Angular 2 项目,并且正在考虑是使用 Reactive Forms 还是 Template Forms。背景阅读此处:https://angular.io/guide/reactive-forms

据我所知,Reactive Forms 的最大优点是它们是同步的,但我们有简单的表单,我认为异步不会给我们带来问题。 Reactive 似乎有更多的开销,表面上有更多的代码来做同样的事情。

有人可以提供一个可靠的用例,让我可以在更简单的模板表单上使用 Reactive 吗?

这是我的 Forms in Pluralsight 课程中的一张幻灯片。其中一些观点可能有争议,但我与开发表单的 Angular 团队的人员合作,将此列表放在一起。

模板驱动设计的优点是简单。控制器中不会有太多代码。大多数逻辑发生在模板中。这适用于在 html 代码背后不需要太多逻辑的简单表单。

但每个表单都有一个状态,可以通过许多不同的交互进行更新,应用程序开发人员需要管理该状态并防止其损坏。这对于非常大的表单来说很难做到,并且会引入错误。

另一方面,如果需要更多的逻辑,往往也需要进行测试。然后反应模型驱动设计提供更多。我们可以对表单验证逻辑进行单元测试。我们可以通过实例化 class、在表单控件中设置一些值并执行测试来做到这一点。对于复杂的软件,这是设计和可维护性所绝对需要的。反应模型驱动设计的缺点是它的复杂性。

还有一种混合两种设计类型的方法,但这会同时具有两种类型的缺点。

您可以在此处找到针对这两种方式的简单示例代码的解释: Introduction to Angular Forms - Template Driven vs Model Driven or Reactive Forms

在幕后他们是一样的。在反应形式中,这就是你在 app.module.ts:

中导入的内容
import { ReactiveFormsModule } from '@angular/forms';

imports: [BrowserModule, ReactiveFormsModule],

然后在你的 parent.component.ts

import { FormGroup, FormControl, Validators } from '@angular/forms';

cardForm = new FormGroup({
name: new FormControl('', [
  Validators.required,
  Validators.minLength(3),
  Validators.maxLength(5),
]), 

});

cardForm 是 FormGroup 的一个实例。我们需要将它连接到表单本身。

<form [formGroup]="cardForm" (ngSubmit)="onSubmit()"></form>

这表示此表单将由“cardForm”处理。在表单的每个输入元素中,我们将添加控制器以监听所有更改并将这些更改传递给“cardForm”。

<form [formGroup]="cardForm" (ngSubmit)="onSubmit()">
      <app-input label="Name" [control]="cardForm.get('name')"> </app-input>
 </form>


 cardForm.get('name')=  new FormControl('initValue', [
                           Validators.required,
                           Validators.minLength(3),
                           Validators.maxLength(5),
                           ]), 

简而言之,FormControl 实例放置在输入元素中,它们监听所有变化并将它们报告给 FormGroup 实例。我们正在 class 组件中明确设置 FormGroup 和 FormControl。

如果您使用模板表单,则无需在 parent.component.ts 中设置任何内容。你在 parent.component.html 里面写你的代码。但是此时,angular幕后仍然会创建FormGroup,并通过FormGroup来处理表单。在 app.module.ts

  import { FormsModule } from '@angular/forms';

  imports: [BrowserModule, FormsModule],

我们没有为 FormGroup 和 FormControl 编写任何代码。我们转到模板文件:

 <form (ngSubmit)="onSubmit()" #emailForm="ngForm">

#emailForm 创建对在后台创建的“FormGroup”的引用。这样我们就可以访问 FormGroup 的所有属性,例如“touched”、“valid”等。

然后我们将输入元素放在表单中:

  <input
    type="email"
    required
    name="email"
    [(ngModel)]="email"
    #emailControl="ngModel"
  />
  • ngModel 是指令。告诉 Angular,我们要跟踪此输入中的值。它会将大量事件处理程序附加到输入元素。

  • [(ngModel)] 是双向绑定。 属性 绑定和事件处理语法放在一起。如果 class 中的值“email”发生变化,则更新输入值,同样,如果输入值发生变化,则更新 class 中的“email”。我们已经在 class 组件

    中定义了“电子邮件”
        export class AppComponent {
        email: string; // [(ngModel)] communicates with this
        onSubmit() {
        console.log(this.email);
      }
     } 
    
  • #emailControl 是对输入控件的引用。名字可以是任何东西。

    emailControl===emailForm.controls.email
    

所以在这个模板表单中,#emailForm代表FormGroup,#emailControl代表FormControl。

  • 在响应式表单中,我们在 FormControl 中显式编写验证逻辑。但是对于模板,如果您检查 input 元素,我们会添加“required”。当angular看到这个,它会自动分配给Validator.required