如何创建嵌套和可重用的表单
有关创建嵌套和可重用窗体的深入教程 , 通过使用复合控制值访问器实现完全可靠性。
在本教程中,您将学习如何创建和使用窗体组。我们还将学习如何通过使用复合控制值访问器来实现完全的可靠性。
介绍
在Web应用程序中,我们可以有大型表单,如帐户注册表单,个人资料创建表单,信用卡表单,地址表单等。这些大型表单通常具有一组在其中重复的字段。
例如,地址字段通常在所有注册表单中都可用。在本教程中,我们将学习如何将此类字段包装在可重用表单中,以便它们可以用作任何其他表单中的嵌套表单。
在本教程中,我们将讨论创建表单的 4 种方法,我们还将介绍每种方法的优缺点:
如何创建和使用表单组
如何创建嵌套表单组
如何将子组件与嵌套窗体组一起使用
如何使用复合创建可重用表单ControlValueAccessor
如何创建和使用表单组
窗体通常包含多个相关的控件。反应式窗体提供了两种将多个相关控件分组到单个输入窗体中的方法:和 。在本教程中,我们将重点介绍 .FormGroupFormArrayFormGroup
正如窗体控件实例允许您控制单个输入字段一样,窗体组实例跟踪一组窗体控件实例(例如,窗体)的窗体状态。创建窗体组时,将按名称跟踪窗体组实例中的每个控件。
我们将以“个人资料”表单为例,其中包含姓名、电子邮件、地址行、城市、州、邮政编码和国家/地区的输入字段。
相同的窗体组如下所示:
请注意,我们还利用了 Angular 14 中引入的严格类型化表单功能。
在上面的代码中,我们只是创建了 一个,所有字段都为 .HTML 模板代码可能如下所示:FormGroup FormControl
指令提供的输入将每个单独的输入绑定到 中定义的窗体控件。窗体控件与其各自的元素进行通信。它们还将更改传达给表单组实例,该实例为模型值提供事实来源。formControlNameFormControlNameFormGroup
优点
简单明了的模板和表单组
缺点
难以创建和维护复杂的表单模型
字段集之间缺少逻辑隔离
如何创建嵌套表单组
在构建复杂表单时,在较小的部分中管理不同的信息区域会更容易。使用嵌套表单组实例可以将大型表单组分解为更小、更易于管理的表单组。
让我们对嵌套组中的相关字段进行分组寻址:
请注意,现在在地址中,相关字段按 元素分组。我们还创建了一个类型,以获得更好的类型安全性,并在 IDE 中更好地自动完成。让我们在模板中对嵌套表单进行分组:profile Form address AddressForm
我们添加了 该指令以指示子窗体控件是窗体组的一部分。formGroupNameaddress
优点
易于创建和维护复杂的表单模型
字段集之间存在逻辑隔离
缺点
由于字段更多且表单复杂,模板更大
如何将子组件与嵌套窗体组一起使用
在上一节中,我们在类中实现了逻辑分离,但模板仍然很复杂。我们将创建另一个组件来处理模板复杂性。
我们创建了 .它有一个名为 的输入属性,父组件可以通过它传递表单组。我们来看看模板:AddressForm Component formGroup
该模板非常简单,它只有与地址相关的字段。以下是我们如何在父组件中使用它:
在类中,我们将获得如下所示的地址表单组:
优点
更简单的模板 a.现在,使用这种方法,我们可以处理与 地址相关的所有内容,以便我们的主要组件更易于处理。AddressFormComponent
缺点
不能完全重复使用。如果要将此组件用作独立的表单组件,则目前无法实现。
如何使用复合创建可重用表单ControlValueAccessor
在上一节中,我们创建了一个组件,并将地址表单的模板移动到其中。但是,它仍然不能完全重新启动。通过完全可重用,我的意思是:
逻辑、错误处理和地址表单创建应该是地址组件的一部分,而不是父组件。
该组件应可在任何窗体中使用。
该组件应可用于模板驱动和反应式表单。
该组件应支持本机窗体控件功能,以便父组件或使用者组件可以利用此功能,例如,如果整个地址窗体无效,则显示错误。
在本节中,我们将学习如何创建一个完全可重用的表单,该表单既可以用作其他表单内部,也可以用作独立表单。我们将要使用的技术称为“复合控制值访问器”,由卡拉·埃里克森在2017年角度连接中引用。
我们的目标是使用如下所示的地址表单:
控制值访问器
充当角度表单 API 和 DOM 中的本机元素之间的桥梁。任何组件或指令都可以通过实现接口并将自身注册为提供程序来转换为窗体控件。ControlValueAccessorControlValueAccessorNG_VALUE_ACCESSOR
其中,该接口定义了两个重要方法 — 和 。writeValueregisterOnChange
窗体控件使用写值方法将值设置为本机窗体控件。表单控件使用寄存器OnChange方法注册每次更新本机表单控件时都应触发的回调。您有责任将更新的值传递给此回调,以便更新各个 Angular 窗体控件的值。方法用于指示用户与控件进行了交互。
下图显示了交互:
从 在实现控制值时再也不要混淆以角度形式访问 - 深入的角度
复合控制值访问器
在之前的文章和教程中,我们看到了 with one 的用法。但是,使用的优点是,如果需要,您可以获得更多输入。Control Value Accessor input Control ValueAccessor
我们只需要处理该接口的所有4个必需方法,它就会正常工作,无论我们在内部如何处理它。
可重复使用的表单
上一节中的一件事是明确的,我们希望使用相同的模板,并且在内部,我们将使用表单组管理字段的状态,因此我们的模板将如下所示:
为了管理地址对象,我们将创建一个类。这将在上述模板的类的后期阶段使用:
我们将上面的类作为表单的值。就像 、 和 一样,我们也可以将对象存储在窗体控件中。您可以在有关在窗体控件中管理对象的教程中阅读有关它的更多信息。Address string number boolean
对于验证,您可以有自己的逻辑来验证地址,但现在我们将保持简单。我们将在实现验证时使用它。
接下来,根据前面有关 的文章,我们将从实现接口和 as 提供程序开始:ControlValueAccessorControlValueAccessorNG_VALUE_ACCESSOR
写入值
在这里,我们将首先转换进入实例的值,然后调用并将更新所有字段,其中的值将被更新。Addressform.patchValue
注册更改
我们使用可观察量来处理 。 所有子窗体字段的可观察发射,因此它非常适合 。valueChangesregisterOnChangevalueChangesregisterOnChange
现在,正如我们正在听的那样,我们将不得不重新访问和修复 ,因为每次被调用,都会触发,我们不希望这样。valueChangeswriteValuepatchValuepatchValuevalueChanges
如上文所述,我们将 设置为 ,因此它不会触发 。emitEventfalsevalueChanges
注册一触即发
我们希望只要触及任何子窗体控件,就可以触摸窗体。因此,我们还将使用所有子窗体控件调用模板:onTouched
set禁用状态
验证
为了处理验证,我们将首先添加一个提供程序,并实现接口:Validator
验证
在这里,我们将使用该类的方法,并在此基础上返回错误。AddressisValid
多个实例
虽然我们的表单现在已经准备好使用了,但它仍然存在一个问题。如果在同一 UI 中使用此组件,则窗体控件可能无法正常工作,因为它们都具有相同的 属性。而且,此组件本身没有 ,这可能有助于测试。nameidid
为了解决这个问题,首先让我们介绍一个名为:hostid
接下来,我们将添加一个静态计数器,我们将随此组件的每个实例递增该计数器:
最后,我们将将其用于所有 s' 和属性。还有他们的s'属性:idinputidname label for
这样,我们完全可重复使用的地址表单就准备好了。
结论
在本教程中,我们学习了如何创建和使用表单组。然后,我们学习了如何创建嵌套表单组以及如何将它们与子组件一起使用。通过这些方法中的每一种,我们也了解了它们的利弊。
在最后一个但非常重要的部分中,我们学习了如何使用复合创建完全可重用的表单组件。ControlValueAccessor