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

时间:2017-03-01 12:29:00

标签: angular typescript angular2-forms

我的要求是我需要创建一个包含嵌套组件的表单。 我正在为每个表单字段创建组件,意味着文本框会有 作为一个组件,对于单选按钮,将有另一个组件,如明智 <form [formGroup]="myForm">
<textbox-component></textbox-component>
<radioButton-component></radioButton-component>
</form>

我想使用Reactive表单创建此表单,因为我想要我的 html不受影响,仅通过打字稿进行表单验证。

但是我找不到任何解决方案我们如何能够嵌套反应形式 组件。

5 个答案:

答案 0 :(得分:41)

经过我的研究和研究实验我找到了一个问题的答案,所以我自己回答。如果它节省了某人的时间,那么我会很高兴。

如果您想使用嵌套组件创建反应式表单,则可以执行以下操作

这里我创建一个包含两个嵌套组件的表单,一个用于textbox&amp;其他用于单选按钮

您的父组件可以是这样的

<form [formGroup]="myForm">
    <child-textbox-component [parentFormGroup]="myForm">
    </child-textbox-component>
    <child-radio-button-component [parentFormGroup]="myForm">
    </child-radio-button-component>
</form>

我们将FormGroup对象作为输入传递给在父组件中创建的子组件 作为子组件的输入,他们将在其中使用此FormGroup对象 用于设计类的特定控制的组件

您的孩子组件将是这样的

儿童文本框组分

<div class="form-group" [formGroup]="parentFormGroup">
  <label>
    {{control.caption}}
  </label>
  <input class="form-control" type="text" [title]="control.toolTip" 
    [attr.maxlength]="control.width" [name]="control.name"
    [value]="control.defaultValue" [formControlName]="control.name"/>
</div>

儿童单选按钮组分

<div class="form-group" [formGroup]="parentFormGroup">
  <label>
    {{control.caption}}
  </label>
  <div>
      <label *ngFor="let value of control.values; let idx = index"
        class="radio-inline" [title]="control.tooltip">
        <input type="radio" [name]="control.name" [formControlName]="control.name"/>
        {{ value }}
      </label>
  </div>
</div>

这里控件是保存要为这些显示的数据的模型类 儿童组成部分。

通过这种方式,您可以使用嵌套组件生成表单, 所以你不需要单独的形式(可以说大表格) 零件。您可以将其分解为尽可能多的子组件和形式会 易于创造和保持也使用角度2的反应形式。您也可以轻松添加验证。

在回答此

之前,我已按照这些链接进行操作
  1. something similar on stackoverflow

  2. angular 2 dynamic forms

答案 1 :(得分:1)

对Mhesh的回答补充说明,您可以构建此相同的解决方案,而无需在HTML中注入[parentFormGroup]。您可以在可重复使用的表单组中执行此Stack Overflow post来执行此操作。

这真的很好。

实施例

要采用现有解决方案,您可以执行相同的操作,但:

您的父组件可以是这样的,没有在

中传递任何其他参数
<form [formGroup]="myForm">
    <child-textbox-component></child-textbox-component>
    <child-radio-button-component></child-radio-button-component>
</form>

另外请注意,您可以像这样设置表单组:

<form [formGroup]="myForm">
    <child-textbox-component></child-textbox-component>
    <child-radio-button-component formGroupName="myGroup"></child-radio-button-component>
</form>

儿童文本框组分

<div class="form-group" [formGroup]="controlContainer.control">
  <label>
    {{control.caption}}
  </label>
  <input class="form-control" type="text" [title]="control.toolTip" 
    [attr.maxlength]="control.width" [name]="control.name"
    [value]="control.defaultValue" [formControlName]="control.name"/>
</div>

要启用此功能,您需要在ControlContainer

中注入@Component
@Component({
    moduleId: `MODULE_ID_HERE`,
    selector: "child-textbox-component",
    templateUrl: "childTextbox.component.html",
})
export class ChildTextboxComponent {
    constructor(private controlContainer: ControlContainer, OTHER_PARAMETERS) {
    }
}

答案 2 :(得分:1)

要扩展可能的答案列表,this article by Alexey Zuev建议在组件装饰器中使用provide:ControlContaineruseExisting:NgForm作为将ngForm指令传递到子组件的方法。

@Component({
  selector: 'registrant',
  templateUrl: 'app/register/registrant.component.html',
  **viewProviders: [ { provide: ControlContainer, useExisting: NgForm } ]**
})

答案 3 :(得分:0)

使用[formGroup]绑定在表单块中传递相同或子formGroup。

答案 4 :(得分:0)

尝试使用嵌套的日期选择器时出现相同的问题。上面的解决方案不适用于我。我通过发出更改日期和直接索取控制表来解决问题。

calendar-input.component.ts

@Component({
  selector: 'app-calendar-input',
  templateUrl: '...',
})
export class CalendarInputComponent {
  @Output() dateChanged = new EventEmitter<Date|null>();  
  onClose() {
    this.dateChanged.emit(this.currentDate);
  }
  ...
}

模板

    <app-calendar-input
      ...
      (dateChanged)="setFormControlValueByItem(item, col.propName, $event)">
    </app-calendar-input>

以及具有表单组和表单控件的组件:

  setFormControlValueByItem(item: FormItem<I, FormGroup>, propName: string, value: any): void {
    item.frameworkFormGroup.controls[propName].setValue(value);
    item.frameworkFormGroup.controls[propName].markAsTouched();
    item.frameworkFormGroup.controls[propName].markAsDirty();
  }
在我的情况下,

item.frameworkFormGroup是FormGroup的实例,而propName是我通常会写到属性formControlName的字段名称。

此解决方案的不足之处在于,它使代码在某些情况下不易破坏FormGroup和FormConrol API中的中断。

另请参阅:https://angular.io/api/forms/FormGrouphttps://angular.io/api/forms/FormControl