Angular2:将表单上下文绑定到ngTemplateOutlet [英] Angular2: Bind form context to ngTemplateOutlet

查看:105
本文介绍了Angular2:将表单上下文绑定到ngTemplateOutlet的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图定义一个包含动态表单的组件(使用ReactiveForms),用户应该可以在其中添加/删除控件. 控件可以采用多种形式,并且必须在Component外部进行定义,因此我认为TemplateRef最适合于此.

I'm trying to define a Component containing a dynamic Form (using ReactiveForms) where the user should be able to add / delete Controls. The Controls can take many forms, and has to be defined outside of the Component, so I think that TemplateRef is the most appropriate for this.

我正在努力寻找一种通过使用formControlName将外部定义的控件绑定到内部Form的方法

I'm struggling to find a way to bind the externally defined Control to the internal Form, through the use of formControlName

这是实施的开始:

// expandable.component.ts

[...]
@Component({
  selector: 'expandable',
  templateUrl: 'app/component/common/expandable/expandable.component.html',
  styleUrls: ['app/component/common/expandable/expandable.component.css']
})
export class ExpandableComponent {
  @ContentChild('childTemplate') childTemplate: TemplateRef<any>;

  @Input() children: Array<any>;
  public form: FormGroup;

  constructor(private _changeDetector: ChangeDetectorRef,
              private _formBuilder: FormBuilder) {
    this.children = [];
  }

  public ngOnInit(): void {
    this.form = this._formBuilder.group({
      children: this._formBuilder.array([])
    });

    const arrayControl = <FormArray>this.form.controls['children'];
    this.children.forEach(child => {
      const group = this.initChildForm();
      arrayControl.push(group);
    });
  }

  private initChildForm(): AbstractControl {
    return this._formBuilder.group({
      key: ['Initial Key', [Validators.required]],
      value: ['Initial Value', [Validators.required]]
    });
  }

  public addChild(): void {
    const control = <FormArray>this.form.controls['children'];
    control.push(this.initChildForm());
    this._changeDetector.detectChanges();
  }
}

-

<!-- expandable.component.html -->

<form [formGroup]="form">
  <div class="form-group">
    <div formArrayName="children">
      <div *ngFor="let child of form.controls.children.controls; let i=index">
        <div [formGroupName]="i">
          <template 
             [ngTemplateOutlet]="childTemplate" 
             [ngOutletContext]="{ $implicit: child }"></template>
        </div>
      </div>
    </div>
  </div>
  <a (click)="addChild()">Add Child</a>
</form>

尝试在外部定义模板:

  <expandable>
    <template #childTemplate>
      <input class="form-control" 
        formControlName="value" />
      </template>
  </expandable>

我天真地试图将formControlName绑定到外部的隐式传递的上下文,但是没有运气,因为我收到找不到名称为'value'的控件".理想情况下,我希望能够将formControlName绑定到expandable.component.html中,但是我也看不到这样做的方法.

I'm naively trying to bind the formControlName to the implicitly passed context from the outter , but with no luck, as I'm getting "Cannot find control with name: 'value'". Ideally, I would like to be able to do the formControlName binding into the expandable.component.html instead, but I see no way of doing this either.

对此有何想法?

推荐答案

是的,这是可能的:

您需要实现ngModelformControlName注入的ControlValueAccessor接口,如下所示:

You need to implement the ControlValueAccessor interface which ngModel and formControlName inject, like so:

@Directive({
  selector: 'control',
  providers: [
    {provide: NG_VALUE_ACCESSOR, multi: true, useExisting: SwitchControlComponent}
  ]
})
export class SwitchControlComponent implements ControlValueAccessor {
  isOn: boolean;
  _onChange: (value: any) => void;

  writeValue(value: any) {
    this.isOn = !!value;
  }

  registerOnChange(fn: (value: any) => void) {
    this._onChange = fn;
  }

  registerOnTouched() {}

  toggle(isOn: boolean) {
    this.isOn = isOn;
    this._onChange(isOn);
  }
}

html:

  <expandable>
    <template #childTemplate>
      <div [formGroup]="form">
         <input control class="form-control" 
           formControlName="value" />
         </template>
      </div>
  </expandable>

进一步阅读:

使用新的表单api,如果不添加其他表单标签就无法添加子组件的输入

这篇关于Angular2:将表单上下文绑定到ngTemplateOutlet的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆