【问题标题】:Nested forms in Angular 2 JS (RC4 and newer)Angular 2 JS(RC4 和更新版本)中的嵌套表单
【发布时间】:2017-01-24 10:14:02
【问题描述】:

我想构建一个动态表单组件,它可以接收一个对象并生成一个新表单。我正在使用 Angular RC6

数据示例:

[{
    formgrouplabel: "registration",
    data: [{
        type: "checkbox",
        label: "checkbox 1",
        name: "checkbox1",
        default: false,
        required: false
    }, {
        type: "radio",
        label: "mr",
        name: "sex",
        default: true,
        required: true
    }, {
        type: "radio",
        label: "miss",
        name: "sex",
        default: false,
        required: true
    }]
}, {
    formgrouplabel: "some other part of the form",
    data: [another array with input objects]
}]

实际对象将包含更多信息,例如验证器和其他要求。我还想将输入捆绑到组中。

我构建了相应的角度组件:

<dynamic-form></dynamic-form>
<dynamic-form-group></dynamic-form-group>
<dynamic-checkbox></dynamic-checkbox>
<dynamic-radiobutton></dynamic-radiobutton>

在我的动态表单组模板中,我 *ngFor 遍历数据对象中的所有表单组。然后使用 ngSwitchCase 将复选框对象传递给动态复选框组件,并将单选按钮对象传递给动态单选按钮组件。

现在所有这些都工作得很好,整个表单都生成了,但是:

当我现在在动态复选框组件中使用 ngModel 例如将 FormControl 绑定到输入元素时,ngModel 无法与动态表单组件上的 ngForm 通信(向上两个级别)。 动态表单组组件中的 FormGroup 也无法与 ngForm 通信。简而言之,不允许孩子与父母进行任何交流。

我正在阅读 ng-book 2 和 angular 文档中的所有示例,但我找不到一个干净的解决方案。我知道,如果您希望子元素与其父元素进行通信,您可以创建服务或通过 @Export 和事件发射器导出某个值/对象或函数。然而,这并不会导致一个干净的解决方案。

我现在理解的问题是,当您使用 FormBuilder 或 FormGroup 和 FormControl 时,您必须先实例化控件: this.form = new FormGroup({checkboxControl: new FormControl("some value")});

或(如 ng book 2 中所述)

myForm: FormGroup;
constructor(fb: FormBuilder) { this.myForm = fb.group({
      'sku': ['ABC123']
    });
}

这两个对我来说都不是一个真正的选择。由于对象模型,我的表单将首先创建,然后是我的表单组,最后是我的表单控件。为了使用上述方法,应该反过来。

有没有办法先创建表单组,然后再添加控件? 我已经试过了:

this.form = new FormGroup({});
this.form.controls['newControl'] = new FormControl({"some value"});

这确实向我现有的 FormGroup 添加了一个新的 formControl,但是当该输入上的值发生更改时,formControl 不会更新。就像我只引用了“new FormControl({"some value"});”并且该值始终保持在“某个值”。

最后我也尝试了这种方法: https://angular.io/docs/ts/latest/cookbook/dynamic-form.html

这里他们也先构建表单控件,然后将它们作为对象传递以创建表单组。

当然,我可以将所有模板和控制逻辑放入动态表单组件中,而省去动态表单组、动态复选框和其他组件,但是有什么方法可以让我按我的意愿工作? 我希望有人已经用新的表单 api 构建了一些复杂的东西。

【问题讨论】:

标签: javascript forms angular


【解决方案1】:

看看 FormGroup 上的addControl() 功能。 FormGroup、FormArray、FormControl等内置了很多方便的方法,适用于各种场景。

使用示例

/* 
    basic-form-question.component.ts -> From Angular Dynamic Form Documentation 
*/
@Component({
   selector: 'df-question',
   templateUrl: './basic-form-question.component.html'
})
export class DynamicFormQuestionComponent implements OnInit {
    @Input() question: QuestionBase<any>;
    @Input() form: FormGroup;

    ngOnInit() {
        if(!this.form.controls.hasOwnProperty(this.question.key)){
            let control = new FormControl(this.question.value || '', Validators.required);

            this.form.addControl(this.question.key, control);
        }
    }
}

希望这会有所帮助。

【讨论】:

  • 这似乎工作,我不太喜欢的小调整,但它比以前更好。我将表单组作为对象传递给孩子(例如 DynamicFormQuestionComponent)。这本身是不够的,因为 formControlName 不能绑定到 formGroup,除非在模板中特别提到了 formGroup。我将 formGroup 传递给子元素“parentformgroup”。在子组件模板中,我添加了以下 [formGroup]="parentformgroup"。这达到了我想要的。感谢您的精彩意见!
  • 不幸的是,这似乎是目前在 Angular 2 中以动态形式做事的标准方式,但这是一个小小的警告。不过我的做法是在模板中使用FormControl 而不是FormControlName,因为这样可以避免在模板中声明关系。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-10-23
  • 1970-01-01
  • 2015-10-22
  • 1970-01-01
  • 1970-01-01
  • 2020-08-06
  • 2016-10-18
相关资源
最近更新 更多