构建嵌套的反应形式问题

时间:2016-11-18 11:04:13

标签: angular typescript rxjs observable angular2-forms

我试图建立一个嵌套在两个组件中的反应形式。 ParentComponent工作正常,但我遇到ChildComponent的麻烦。ChildComponent使用ControlValueAccessor。

问题:字段显示在视图中,但更改不会转到父级。为什么?我的ControlValueAccessor功能是否正确?

child.component.html

<ul [formGroup]="fieldsForm">
    <li *ngFor="let field of fields">
      <label>
        <input type="checkbox" [formControlName]="field.$key">
        {{field.$key}}
      </label>
    </li>

</ul>

child.component.ts

import {Component, OnInit, Input, ChangeDetectionStrategy} from '@angular/core';
import {FormGroup, FormBuilder, NG_VALUE_ACCESSOR, ControlValueAccessor} from "@angular/forms";
import {NodeService} from "../../node.service";

@Component({
  selector: 'child',
  templateUrl: './child.component.html',
  styleUrls: ['./child.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush,
  providers: [
    {provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() =>ChildComponent), multi: true}
  ]
})
export class ChildComponent implements OnInit,ControlValueAccessor {

  public fieldsForm: FormGroup;
  public fields: any = [];

  @Input() currentFilter;
  @Input() formControlName;

  constructor(private fb: FormBuilder, private nodeService: NodeService) {
    this.fieldsForm = this.fb.group({});
  }

  ngOnInit() {
    this.getFilterValues(this.formControlName)
    .subscribe(fields => {
      const acc = {};
      this.fields = fields;
      fields.forEach(field => acc[field.$key] = [true]);
      this.fieldsForm = this.fb.group(acc);
    })
  )

  registerOnChange(fn: (value: any) => void) {
    this.fieldsForm.valueChanges.subscribe(fn);
  }

  registerOnTouched() {}

  getFilterValues(type) {
    return this.nodeService.getFilterValues(type, {
      query: { orderByValue: true, equalTo: 1 }
    })
  }

}

parent.component.ts

import {Component, OnInit, ChangeDetectionStrategy} from '@angular/core';
import {FormBuilder, FormGroup} from "@angular/forms";
import {Input} from "@angular/core/src/metadata/directives";
import {Subject} from "rxjs";

@Component({
  selector: 'filter',
  templateUrl: './filter.component.html',
  styleUrls: ['./filter.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class ParentComponent implements OnInit {

  public form: FormGroup;
  public groupsForm:Subject<any> = new Subject();

  @Input() groups;
  @Input() currentFilters;

  constructor(private fb: FormBuilder) {
    this.form = this.fb.group({})
  }

  ngOnChanges() {
    const acc = {};
    this.groups.map(group => {
      acc[group] = [];
    });
    this.groupsForm.next(acc);
  }

  ngOnInit() {
    this.groupsForm.subscribe(groupForm => this.form =     this.fb.group(groupForm));

    // Detect changes from from
    this.form.valueChanges
     .subscribe(console.log)
  }

}

parent.component.html

<form [formGroup]="form" novalidate>
  <fieldset *ngFor="let group of groups">

    <child [formControlName]="group" [currentFilter]="currentFilters[group]"></child>

  </fieldset>
</form>

过去3周我一直在这张表格上。我已经用两种类型的表单,嵌套或单个组件完成了它。我想使用ControlValueAccessor。我希望有人可以帮助我。谢谢!

1 个答案:

答案 0 :(得分:0)

您不应该在更高级别注册提供商吗?例如。在ParentComponent?现在NG_VALUE_ACCESSOR及其子级可以使用ChildComponent

我有一种不同的方法来混合嵌套组件和反应形式 - 只需将FormGroup作为@Input传递给子级。 Works for me