Элементы управления угловой формы в пользовательском компоненте

Я создаю сложную форму на основе шаблонов с помощью Angular 2, которая получает структуру групп и полей из API. API отправляет объект JSON, содержащий группы, которые могут содержать поля и / или подгруппы. Поскольку группы могут иметь подгруппы, я думаю, что самый простой способ справиться с этим - иметь настраиваемый элемент управления FieldGroupComponent, который принимает входной параметр «Группа», и если группа содержит подгруппы, он будет отображать их рекурсивно, с помощью FieldGroupComponent.

Проблема, с которой я столкнулся, заключается в том, что ngForm не распознает элементы управления вводом в FieldGroupComponent как FormControls. NgForm считает, что у него нет элементов управления, и не распознает, что поля недействительны.

Страница формы выглядит примерно так:

<form ngForm (ngSubmit)="submitForm()">
  <field-group *ngFor="let group of FormGroups" [group]="group"></field-group>
</form>

И FieldGroupComponent:

@Component({
  selector: "field-group",
  templateUrl: "./field-group.component.html"
})
export class FieldGroupComponent {
  @Input("group") group;
}

И шаблон FieldGroupComponent:

<fieldset>
  <h1>{{group.Title}}</h1>
  <div *ngFor="let field of group.Fields">
    ... render field ...
  </div>
  <div *ngFor="let subGroup of group.FieldGroups">
    <field-group [group]="subGroup"></field-group>
  </div>
</fieldset>

person SZH    schedule 13.02.2017    source источник
comment
Вы проверили этот angular.io/docs/ts/latest/cookbook/ dynamic-form.html   -  person DraganS    schedule 14.02.2017
comment
Если вы хотите использовать пользовательские компоненты в формах, они должны реализовывать ControlValueAccessor.   -  person Günter Zöchbauer    schedule 14.02.2017


Ответы (2)


В итоге я просто передал NgForm в FieldGroupComponent как @Input и вручную добавил элементы управления полем в форму:

@Input("form") form: NgForm;
@ViewChildren(NgModel) private formControls: QueryList<NgModel>;

ngAfterViewInit(): void {
  this.formControls.forEach((item: NgModel) => this.form.addControl(item));
}
person SZH    schedule 15.02.2017
comment
Это сработало? Как вы реализовали проверку, то есть как форма узнает, заполнены ли, например, требуемые поля или нет? - person mwager; 06.09.2017

Моя форма была динамической, поэтому я расширил решение SZH ngAfterViewInit, поэтому элементы управления formControls перестраиваются при каждом изменении. M

В некоторых случаях может вызвать некоторые проблемы с производительностью, но если вам это нужно, он обновляет элементы управления формой:

public ngAfterViewInit(): void {
    this._formControls.changes.subscribe(() => {
        this._formControls.forEach((item: NgModel) => {
            if (!this.form.controls[item.name]) {
                this.form.addControl(item);
            }
        });
    });
}

person michal.jakubeczy    schedule 21.04.2020