Angular2 嵌套模板驱动表单 [英] Angular2 nested template driven form

查看:24
本文介绍了Angular2 嵌套模板驱动表单的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这简直是疯了,看起来没有办法让表单的其中一个输入位于子组件中.

我已经阅读了所有的博客和教程以及所有内容,但没有办法解决这个问题.

问题是当子组件将有任何类型的表单指令(ngModel、ngModelGroup 或其他任何……)时,它就无法工作.

这只是模板驱动表单的问题

这是plunker:

import { Component } from '@angular/core';@成分({选择器:'子表单组件',模板:`<fieldset ngModelGroup="地址"><div><label>街道:</label><input type="text" name="street" ngModel>

<div><label>邮编:</label><input type="text" name="zip" ngModel>

<div><label>城市:</label><input type="text" name="city" ngModel>

</fieldset>`})导出类 childFormComponent{}@成分({选择器:'表单组件',指令:[childFormComponent],模板:`<form #form="ngForm" (ngSubmit)="submit(form.value)"><fieldset ngModelGroup="name"><div><label>名字:</label><input type="text" name="firstname" ngModel>

<div><label>姓氏:</label><input type="text" name="lastname" ngModel>

</fieldset><child-form-component></child-form-component><button type="submit">提交</button></表单><预>{{form.value |json}}

<h4>已提交</h4><预>{{值|json }}

`})导出类 FormComponent {价值:任何;提交表格) {this.value = 形式;}}

解决方案

一个简单的解决方案是在您的子组件的 viewProviders 数组中提供 ControlContainer ,例如:

import { ControlContainer, NgForm } from '@angular/forms';@成分({...,viewProviders: [ { 提供: ControlContainer, useExisting: NgForm } ]})导出类 ChildComponent {}

Stackblitz 示例

另请阅读这篇文章,解释其工作原理.

更新

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

@Component({选择器:'my-form-child',模板:`<input formControlName="age">`,视图提供者:[{提供:ControlContainer,useExisting: FormGroupDirective}]})导出类 ChildComponent {构造函数(私有父级:FormGroupDirective){}ngOnInit() {this.parent.form.addControl('age', new FormControl('', Validators.required))}}

Ng-run 示例

更新 2

如果您不确切知道哪种类型的 ControlContainer 包装了您的自定义组件(例如您的控件在 FormArray 指令中),那么只需使用通用版本:

import { SkipSelf } from '@angular/core';从@angular/forms"导入{ ControlContainer};@成分({...,视图提供者:[{提供:ControlContainer,useFactory: (容器: ControlContainer) =>容器,deps: [[new SkipSelf(), ControlContainer]],}]})导出类 ChildComponent {}

Ng-run 示例

This is just madness , looks like there is no way to have a form which one of it's inputs is in a child component .

I have read all the blogs and tutorials and everything , no way to work this out .

The problem is when a child component is going to have any kind of form directives ( ngModel , ngModelGroup or whatever ..) , it wont work.

This is only a problem in template driven forms

This is the plunker :

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; 
  }
}

解决方案

One simple solution is to provide ControlContainer in viewProviders array of your child component like:

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

@Component({
 ...,
 viewProviders: [ { provide: ControlContainer, useExisting: NgForm } ]
})
export class ChildComponent {}

Stackblitz Example

Read also this article that explains why it's working.

Update

If you're looking for nested model driven form then here is the similar approach:

@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-run Example

Update 2

If you don't know exactly which type of ControlContainer wraps your custom component(for example your controls is inside FormArray directive) then just use common version:

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 {}

Ng-run Example

这篇关于Angular2 嵌套模板驱动表单的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
其他开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆