如何在表单模型中的值更新时强制进行Angular 2更改检测?

时间:2017-02-07 15:36:47

标签: angular angular2-template angular2-forms

好吧,让我先描述一下我实际想要解决的问题。

我需要我的表单模型才能拥有这个结构:

{
  nested: {
    first: 'one',
    second: 'two',
    third: 'three',
    forth: 'four', ...
  }, ...
}

子属性将根据用户输入动态添加到模型中,嵌套级别的数量可能会有所不同。

实现看起来像这样:

初始化表单:

ngOnInit() {
  this.form = this.fb.group({
    nested: this.getControls() // of type FormGroup
  });
}

加载控件:

getControls(): FormGroup {
  let group: FormGroup = new FormGroup({});
  Object.keys(this.controls).forEach((key) => {
    let control: FormControl = new FormControl(this.controls[key]);
    group.addControl(key, control);
  })
  return group
}

带* ngFor的模板:

<div *ngFor="let control of form.get('nested').controls | keys; let i = index">
  <label>{{ getLabel(i) }}</label>
  <input [attr.placeholder]="control.value">
</div>

添加新的控制方法:

addControl(key, value) {
  let control: FormControl = new FormControl(value)
  this.form.get('nested').addControl(key, control);
  this.cdf.detectChanges();
}

Plunkr

上的精简实施

现在,我遇到的问题是模型的值更新,但模板没有使用添加的输入重新渲染。

我试图强制更改检测,但它没有起作用。

我知道使用FormArray提供了更多动态功能,但它会产生一个输出:

{
  nested: [
    { first: 'one' },
    { second: 'two' },
    { third: 'three' },
    { forth: 'four' }, ...
  ], ...
}

这让我们回到了问题的根源。

当然,我可以利用一个函数,在将模型推送到数据库之前将模型转换回所需的格式,但是假设模型可以在树中的不同级别具有多个不同的属性,而对于某些我来说可能会显示为数组而某些可能不显示,事情很容易变得过于复杂。

这使我得到了FormGroup,但是如何在应用新输入时确保模板呈现?谢谢!

1 个答案:

答案 0 :(得分:2)

我可以为您提供以下解决方案:

1)使用impure pipe

@Pipe({
  name: 'keys',
  pure: false
})

<强> Plunker Example

2)添加控件后传递新引用

addControl(key, value) {
  this.controls[key] = value;
  this.form = this.fb.group({
    nested: this.getControls()
  });
}

<强> Plunker Example

我还删除了getLabel函数并将映射控件名称添加到管道

keyArr.forEach((key) => {
   value[key].name = key;
   dataArr.push(value[key])
})

另见