以 angular2 模型驱动形式重用组件

Posted

技术标签:

【中文标题】以 angular2 模型驱动形式重用组件【英文标题】:Reuse components in angular2 model driven forms 【发布时间】:2017-04-14 23:09:19 【问题描述】:

我对 angular2 还很陌生,过去几天我一直在尝试使用模型驱动的表单创建可重用的表单组件

假设我们有一个组件componentA.component.ts

@Component(
    selector: 'common-a',
    template: `
    <div [formGroup]="_metadataIdentifier">
        <div class="form-group">
        <label>Common A[1]</label>
        <div>
            <input type="text" formControlName="valueA1">
            <small>Description 1</small>
        </div>
        <div class="form-group">
        <label>Common A[2]</label>
        <div>
            <input type="text" formControlName="valueA2">
            <small>Description 2</small>
        </div>
    </div>
    `
)


export class ComponentA implements OnInit

    @Input('group')
    public myForm: FormGroup;

    constructor(private _fb: FormBuilder) 
    

    ngOnInit() 
        this.myForm = this._fb.group(
            valueA1 : ['', [Validators.required]],
            valueA2 : ['', [Validators.required]],
        );
    

还有一个组件 B componentB.component.ts

@Component(
    selector: 'common-b',
    template: `
    <div [formGroup]="_metadataIdentifier">
        <div class="form-group">
        <label>Common B</label>
        <div>
            <input type="text" formControlName="valueB">
            <small>Description</small>
        </div>
    </div>
    `
)


export class ComponentB implements OnInit

    @Input('group')
    public myForm: FormGroup;

    constructor(private _fb: FormBuilder) 
    

    ngOnInit() 
        this.myForm= this._fb.group(
            valueB : ['', [Validators.required]]
        );
    

我的问题是如何使用这两个子组件组成一个表单,而无需将输入的控制移至主组件。 例如main.component.ts

@Component(
    selector: 'main',
    template: `
    <form [formGroup]="myForm" (ngSubmit)="onSubmit(myForm.value)">
        <div>
            <common-a [group]="formA"></common-a>
            <common-b [group]="formB"></common-b>
            <div>
                <button>Register!</button>
            </div>
        </div>
    </form>
    `
)


export class Main implements OnInit

    @Input('group')
    public myForm: FormGroup;

    public formA : FormGroup;

    public formB : FormGroup;

    constructor(private _fb: FormBuilder) 
    

    ngOnInit() 
        this.myForm = this._fb.group(
            //how can I compose these two sub forms here
            //leaving the form control names agnostic to this component
        );
    

这个想法背后的概念是构建许多复杂的表单,这些表单共享它们的一些构建块。

也就是说,我不希望我的 Main 组件知道 formControlNames [valueA1,valueA2,valueB] 的名称,而是自动插入它们并在顶层更新/验证表单组。

任何指向正确方向的想法或点都会有所帮助。

【问题讨论】:

【参考方案1】:

这可以通过将我们的***FormGroup 传递给子组件并让子组件使用formGroupName 将自己添加到更高级别FormGroup 来完成,这样上级FormGroup 基本上需要知道没有关于较低级别的:

ma​​in.component.ts

template: `<...>
    <common-a [parentForm]="myForm"></common-a>
    <...>

我们还将去掉不再使用的 formA、formB 声明。

component-a.component.ts [formGroup] 是我们的父组,formGroupName 是我们将组件的控件作为一个组识别和附加以在更大的整体中工作的方式(它们将嵌套在父组内)。

@Component(<...>
template: `
<div [formGroup]="parentForm">
    <div class="form-group">
    <label>Common A[1]</label>
    <div formGroupName="componentAForm">
        <input type="text" formControlName="valueA1">
        <small>Description 1</small>
    </div>
    <div class="form-group">
    <label>Common A[2]</label>
    <div formGroupName="componentAForm">
        <input type="text" formControlName="valueA2">
        <small>Description 2</small>
    </div>
</div>`
)

export class ComponentA implements OnInit 
     @Input() parentForm: FormGroup;
     componentAForm: FormGroup;

     constructor(private _fb: FormBuilder) 

     ngOnInit() 
         this.componentAForm = this._fb.group(
             valueA1: ['', Validators.required],
             valueA2: ['', Validators.required]
         );

         this.parentForm.addControl("componentAForm", this.componentAForm);
     

这是一个 plunker(请注意,我在这里让组件 B 更动态一点只是为了看看它是否可以完成,但上面的实现同样适用于 B):http://plnkr.co/edit/fYP10D45pCqiCDPnZm0u?p=preview

【讨论】:

非常感谢,这真的很有帮助,让人大开眼界:) Angular 新手,立即开始使用模型驱动的表单。出于好奇,这种共享 FormGroup 字段的方法是推荐的方法还是解决方法?我正在构建一个复杂的系统,我尝试专注于开发小型组件,然后在父子关系中重用它们(4-5 级)。

以上是关于以 angular2 模型驱动形式重用组件的主要内容,如果未能解决你的问题,请参考以下文章

如何使用模型驱动/反应形式修改指令中的输入值

模型驱动形式:验证在 Angular 2 中无法按预期工作

Angular 2.0 中的模型驱动表单验证问题

自定义选择组件的Angular2变换模型

Angular2中的复选框组处理和验证

USB设备驱动模型和输入子系统