2016-11-18 23 views
0

我试图建立一个嵌套在2个组件中的反应形式。 的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。我希望有人能帮助我。谢谢!

+0

哪个'console.log()',你的代码里没有? – n00dl3

+0

我已经添加它。它在订阅'this.filtersValues $' – Tom

回答

0

你不应该只登记在更高层次上的提供者?例如。在ParentComponent?现在NG_VALUE_ACCESSOR可用于ChildComponent及其子女。

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