2016-11-18 45 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