将自定义组件添加到反应式表单的 FormGroup 的正确方法是啥?

Posted

技术标签:

【中文标题】将自定义组件添加到反应式表单的 FormGroup 的正确方法是啥?【英文标题】:What is the correct way to add a custom component to a reactive form's FormGroup?将自定义组件添加到反应式表单的 FormGroup 的正确方法是什么? 【发布时间】:2019-03-22 14:28:12 【问题描述】:

我在包装 mat-select 的自定义组件上使用 formControlName 时遇到很多问题。

现在看来我的自定义控件找不到表单组?即使自定义元素嵌套在 formGroup 下。

我有一个StackBlitz

但是当我将自定义组件嵌套在 formGroup 下时,问题就出现了,所有其他控件都可以找到 formGroup,但我的自定义组件似乎无法找到。

<form novalidate [formGroup]="tenantForm">
    <label for="Id">Id</label>: <input class="form-control" formControlName="id" id="Id" name="Id" />
    <custom-component-with-mat-select formControlName="culture" id="Culture" name="Culture"></custom-component-with-mat-select>
</form>

在本例中,Id 字段可以正常工作,但 Culture 字段抱怨没有嵌套在 FormGroup 中?

错误:formControlName 必须与父 formGroup 指令一起使用。您需要添加一个 formGroup 指令并将一个现有的 FormGroup 实例传递给它(你可以在你的类中创建一个)。

自定义组件应该如何使用响应式表单和表单组?

我最初的问题是不记得导入 ReactiveFormsModule.. 也许我忘了再次导入一些东西?

这是answer 的设计方法吗?还是我错过了更简单的解决方案??

我需要实现一个控制值访问器吗? 如解释here

只是对设计的方式感到困惑。

我的组件包装了角度材料的垫选择,我想我是否需要将属性放在垫选择上或让我的组件实现控制值访问器?似乎没有任何效果。

【问题讨论】:

你想通过formControlName的绑定来完成什么?您的 stackblitz 看起来正在使用响应式表单。 好吧,您的代码与 formControlName="name" 和名称变量“animationType”完美配合。我在编辑时没有看到错误 【参考方案1】:

控件formControlName必须是字符串值。

案例一

formControlName="animationType"

自从animtationType 开始工作,这里是字符串值。

案例 2

[formControlName]="'animationType'" 

这是抛出错误,因为 Angular 正在评估 animationType 的值,这是一个数组(在 ts 文件中定义)

案例 3

formControlName="animationType" 

这与案例 2 的失败原因相同

修复

如果你想访问 formControlName 然后在 ts 中使用字符串值 例如:

** 在 ts 中 **

public animationControl = "animation";

** 在 html 中 **

<mat-select name="animationType" [formControlName]="'animationControl'" 

【讨论】:

【参考方案2】:

我做了一些研究,并让它与控制值访问器一起工作:

https://stackblitz.com/edit/mat-select-with-controlvalueaccessor

【讨论】:

他告诉你他正在尝试使用普通输入的包装器。所以这个解决方案实际上并不能解决他提到的问题。不过,下面的解决方案实际上解决了这个问题【参考方案3】:

我使用参数“formControl”而不是“formControlName”解决了这个问题,如下所示: input-date.compoenent.html

<p-calendar [formControl]="control"></p-calendar>

parent.component.html

<input-date [control]="formGroup.controls.date"></input-date>

其中 control 是 input-date.component 的输入:

@Input() control: FormControl;

【讨论】:

以上是关于将自定义组件添加到反应式表单的 FormGroup 的正确方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章

错误:formControlName 必须与父 formGroup 指令一起使用。您需要添加一个 formGroup 指令 - Angular 反应式表单

Angular - 将自定义验证器分配给 FormGroup

FormArray 字段的角度自定义验证(反应式表单)

Angular 2 使用嵌套组件创建反应式表单

角反应嵌套形式

FormGroup.patchValue 保持子控件的禁用状态