2016-11-10 4 views
2

Я пытаюсь определить компонент, содержащий динамическую форму (используя ReactiveForms), где пользователь должен иметь возможность добавлять/удалять элементы управления. Элементы управления могут принимать различные формы и должны быть определены за пределами Компонента, поэтому я считаю, что TemplateRef является наиболее подходящим для этого.Angular2: привязать форму формы к ngTemplateOutlet

Я изо всех сил, чтобы найти способ связать внешне определенный контроль на внутренней форме, посредством использования 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 с неявным переданным контекстом от внешнего источника, но не повезло, поскольку я получаю «Не могу найти элемент управления с именем:« значение ». В идеале я хотел бы использовать привязку formControlName к expandable.component.html, но я тоже не вижу возможности сделать это.

Любые мысли об этом?

ответ

3

Да, это возможно:

Вы должны реализовать интерфейс ControlValueAccessor который ngModel и formControlName инъекционные, например, так:

@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> 

Дальнейшее чтение:

With new forms api, can't add inputs from child components without adding additional form tags

Смежные вопросы