为了账号安全,请及时绑定邮箱和手机立即绑定

Angular2嵌套模板驱动形式

/ 猿问

Angular2嵌套模板驱动形式

烧仙草VB 2019-10-09 16:59:18

这简直是疯狂,看起来没有办法让其中一种输入形式存在于子组件中。


我已经阅读了所有博客和教程以及所有内容,没有办法解决。


问题是,当子组件将具有任何形式的形式指令(ngModel,ngModelGroup或任何其他..)时,它将无法工作。


这只是模板驱动形式中的一个问题


这是个笨蛋:


import { Component } from '@angular/core';


@Component({

  selector: 'child-form-component',

  template: ` 

  <fieldset ngModelGroup="address">

    <div>

      <label>Street:</label>

      <input type="text" name="street" ngModel>

    </div>

    <div>

      <label>Zip:</label>

      <input type="text" name="zip" ngModel>

    </div>

    <div>

      <label>City:</label>

      <input type="text" name="city" ngModel>

    </div>

  </fieldset>`

})


export class childFormComponent{



}


@Component({

  selector: 'form-component',

  directives:[childFormComponent],

  template: `

    <form #form="ngForm" (ngSubmit)="submit(form.value)">

      <fieldset ngModelGroup="name">

        <div>

          <label>Firstname:</label>

          <input type="text" name="firstname" ngModel>

        </div>

        <div>

          <label>Lastname:</label>

          <input type="text" name="lastname" ngModel>

        </div>

      </fieldset>


      <child-form-component></child-form-component>


      <button type="submit">Submit</button>

    </form>


    <pre>

      {{form.value | json}}

    </pre>


    <h4>Submitted</h4>

    <pre>    

      {{value | json }}

    </pre>

  `

})

export class FormComponent {


  value: any;


  submit(form) {

    this.value = form; 

  }

}


查看完整描述

3 回答

?
哈士奇WWW

一个简单的解决方案是提供ControlContainer在viewProviders像你的孩子组成的数组:


import { ControlContainer, NgForm } from '@angular/forms';


@Component({

 ...,

 viewProviders: [ { provide: ControlContainer, useExisting: NgForm } ]

})

export class ChildComponent {}

Stackblitz示例


另请阅读这篇文章,解释其为何起作用。


Angular:嵌套模板驱动形式

更新资料


如果您正在寻找嵌套模型驱动的表单,那么这里是类似的方法:


@Component({

  selector: 'my-form-child',

  template: `<input formControlName="age">`,

  viewProviders: [

    {

      provide: ControlContainer,

      useExisting: FormGroupDirective

    }

  ]

})

export class ChildComponent {

  constructor(private parent: FormGroupDirective) {}


  ngOnInit() {

    this.parent.form.addControl('age', new FormControl('', Validators.required))

  }

}

Ng运行示例


更新2

如果您不知道确切的ControlContainer包装类型是您的自定义组件(例如,控件位于FormArray指令内),则只需使用通用版本:


import { SkipSelf } from '@angular/core';

import { ControlContainer} from '@angular/forms';


@Component({

 ...,

 viewProviders: [{

   provide: ControlContainer,

   useFactory: (container: ControlContainer) => container,

   deps: [[new SkipSelf(), ControlContainer]],

 }]

})

export class ChildComponent {}


查看完整回答
反对 回复 2019-10-09
?
慕田峪7331174

通过阅读一系列相关的github问题[1] [2],我还没有找到一种简单的方法来使Angle Component向父级添加孩子的控件ngForm(有些人也称它们为嵌套形式,嵌套输入或复杂控件) 。


因此,在这里我要展示的是一种对我有效的解决方法,它ngForm为父母和孩子使用单独的指令。它不是完美的,但是它使我离得足够近,以至于我停在那里。


我childFormComponent用ngForm指令声明我的指令(即,它不是 html表单标签,仅是指令):


<fieldset ngForm="addressFieldsForm" #addressFieldsForm="ngForm">

  <div class="form-group">

    <label for="email">Email</label>

    <input type="email" class="form-control" [(ngModel)]="model.email" name="email" #email="ngModel" required placeholder="Email">

  </div>

  ...

然后,组件将公开addressFieldsForm为属性,并将自身导出为模板引用变量:


@Component({

  selector: 'mst-address-fields',

  templateUrl: './address-fields.component.html',

  styleUrls: ['./address-fields.component.scss'],

  exportAs: 'mstAddressFields'

})

export class AddressFieldsComponent implements OnInit {

  @ViewChild('addressFieldsForm') public form: NgForm;

  ....

然后,父表单可以使用子表单组件,如下所示:


  <form (ngSubmit)="saveAddress()" #ngFormAddress="ngForm" action="#">

    <fieldset>

      <mst-address-fields [model]="model" #addressFields="mstAddressFields"></mst-address-fields>

      <div class="form-group form-buttons">

        <button class="btn btn-primary" type="submit" [disabled]="!ngFormAddress.valid || !addressFields.form.valid">Save</button>

      </div>

    </fieldset>

  </form>

请注意,“提交”按钮显式检查ngFormAddress和addressFields表单上的有效状态。这样,即使它有一些样板,我也可以至少合理地构成复杂的形式。


查看完整回答
反对 回复 2019-10-09
?
偶然的你

另一个可能的解决方法:


@Directive({

    selector: '[provide-parent-form]',

    providers: [

        {

            provide: ControlContainer,

            useFactory: function (form: NgForm) {

                return form;

            },

            deps: [NgForm]

        }

    ]

})

export class ProvideParentForm {}

只需将此指令放在子组件中节点层次结构顶部的某个位置(在任何ngModel之前)。


工作原理:NgModel 使用@Host()限定父窗体的依赖关系查找。因此,父组件中的表单对于子组件中的NgModel不可见。但是我们可以使用上面演示的代码将其注入并提供给子组件。


查看完整回答
反对 回复 2019-10-09

添加回答

回复

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信