在 MEAN Stack 中将表单从模板驱动方法转换为响应式方法

17 Mar 2025 | 5 分钟阅读

在前一节中,我们学习了如何在 angular 应用程序中添加输入文件按钮。我们使用了文件输入和一个 angular material 按钮。在本节中,我们将把输入注册到我们的表单中。为此,我们需要将表单从模板驱动方法转换为响应式方法。在本节中,我们还将学习如何将表单从模板驱动方法转换为响应式方法。

在响应式方法中,我们在我们的 typescript 代码中定义一切,并告诉 angular 我们定义的哪些控件映射到哪些输入。

我们将使用以下步骤来完成

1) 如果我们想使用响应式方法,我们需要导入 ReactiveFormsModule,而不是从 @angular/forms 导入 FormsModule 到我们的 app.module.ts 中。 FormsModule 解锁了模板驱动方法。我们将把这个模块添加到 imports 数组中,如下所示


Converting a Form from a Template Driven approach to Reactive approach in MEAN Stack

2) 我们需要禁用我们 post-create.component.ts 中的 ngModel。我们将摆脱 ngModel 和验证器。从表单中删除 ngModel 后,我们的 html 代码将如下所示


Converting a Form from a Template Driven approach to Reactive approach in MEAN Stack

上面,我们还删除了我们在 onAddPost() 方法中传递的参数,因为我们不能再在模板中访问表单了。

3) 在我们的 typescript 文件中,我们需要改变我们创建表单的方式。因此,我们将在 typescript 文件中以编程方式创建我们的表单。我们将创建表单并将其存储在一个类型为 FormGroup 的 "form" 属性中。所以,我们需要从 @angular/forms 导入 FormGroup 并删除 ngForm


Converting a Form from a Template Driven approach to Reactive approach in MEAN Stack

FormGroup 是表单的顶层对象,并将它的所有控件分组。我们也可以在表单中创建子组,然后在表单中对控件进行分组,但总的来说,表单只是一个大组,我们将使用它。

4) 我们将以以下方式创建类型为 FormGroup 的 form 属性


Converting a Form from a Template Driven approach to Reactive approach in MEAN Stack

我们得到了表单,但它是未定义的。因此,我们需要初始化我们拥有的控件,我们将在 ngOnInit 中完成。我们将访问 ngOnInit(),并且在这个方法的开头,我们将以下列方式进行初始化

因此,我们创建了一个新的 FormGroup 对象,这个对象接受一个 Javascript 对象作为参数。在这个 javascript 对象中,我们将配置我们的表单。我们可以在这个对象中分配键值对来描述我们的控件。我们将以下列方式添加 title 控件


Converting a Form from a Template Driven approach to Reactive approach in MEAN Stack

在上面的代码中,FormControl 在表单中创建一个单独的控件。在 FormControl() 方法中,我们传递了几个参数。 FormControl 函数中的第一个参数是开始表单状态。我们传递 null 作为第一个参数,因为我们希望默认从 null 开始,以拥有一个空的输入。

FormControl 中的下一个参数允许我们附加验证器或表单控件选项。这些对象是 javascript 对象,并且在该对象中,我们定义了诸如异步验证器、同步验证器之类的内容。因此,在上面的代码中,我们将我们的验证器的 javascript 对象作为第二个参数传递。

我们将对内容执行相同的操作,如下所示


Converting a Form from a Template Driven approach to Reactive approach in MEAN Stack

现在,我们基本上得到了与以前相同的表单,当然,表单还没有完成。缺少的东西是与模板的连接以及我们可以用具体值预先填充这些控件的部分(如果我们正在编辑帖子)。因为我们将起始值设置为 null,但这仅在我们创建新帖子时才正确。

5) 我们将回到我们的订阅以设置初始值,我们在那里获得了我们的帖子数据。之后,我们将访问我们的表单并调用 setValue() 方法。此方法允许我们覆盖表单控件的值。因此,我们将在 setValue() 方法中传递一个 javascript 对象,并以下列方式为每个表单控件设置一个值


Converting a Form from a Template Driven approach to Reactive approach in MEAN Stack

6) 现在,我们初始化了值,以防我们得到一个加载的帖子。当我们保存帖子时,将不需要将表单作为参数获取。相反,我们在我们的类中注册了自己的表单对象作为属性。因此,我们将使用 this.form 访问它。我们将使用 form 作为无效属性,访问 value 属性,并在 updatePost() 方法中访问 title 和 content 值。


Converting a Form from a Template Driven approach to Reactive approach in MEAN Stack

7) 现在,要重置表单,我们将调用 this.form.reset() 方法,而不是以下列方式调用 resetForm() 方法


Converting a Form from a Template Driven approach to Reactive approach in MEAN Stack

8) 现在,我们完成了 typescript 代码,缺少的是将我们的 HTML 代码同步到我们的 typescript 的部分。为此,我们将返回到我们的 post-create.component.ts 文件,在这里我们删除了 name,因为 angular 提供了定义 no name 的灵活性。因此,我们不是依赖于某些东西,而是添加了一个特殊的指令。但是,首先,我们将 formGroup 指令添加到我们的整个表单中,并且此 FormGroup 指令采用我们的 form 对象。此 form 对象告诉 angular 我们在 typescript 中创建的表单是 HTML 表单。


Converting a Form from a Template Driven approach to Reactive approach in MEAN Stack

9) 现在,在输入上,我们将使用 formControlName 指令,并且控件的名称与我们在 post-create.component.ts 文件中定义的相同,如下所示

现在,我们在 <mat-error> 中得到了 title.invalid 错误。因此,我们将连接此错误。我们需要通过访问整个表单并使用 get() 方法来访问我们的 title 表单控件。此方法使我们可以访问控件。在此方法中,我们以下列方式将控件名称作为 title 传递


Converting a Form from a Template Driven approach to Reactive approach in MEAN Stack

我们将对我们的文本区域执行这两项操作,如下所示


Converting a Form from a Template Driven approach to Reactive approach in MEAN Stack

现在,如果我们运行 angular 应用程序,我们将再次拥有一个可用的表单。

Converting a Form from a Template Driven approach to Reactive approach in MEAN Stack

我们成功地将表单从模板驱动方法转换为响应式方法。在下一节中,我们将添加图像控件以存储图像。