В этой статье мы покажем, как реализовать формы из вложенных компонентов с реактивным АПИ ангуляра.
С реактивным подходом мы создаем модель формы и передаем эту модель (или ее часть) из одного компонента другому через входящие свойства.
Создадим реактивную форму из нескольких вложенных компонентов
Основной компонент формы NestedFormComponent
Давайте рассмотрим основной компонент формы NestedFormComponent
и то, каким образом мы реализуем в нем будущие компоненты формы. Особенно стоит обратить внимание как мы создаем модель формы в верхнем компоненте NestedFormComponent
. Модель формы будем пробрасывать в дочерние компоненты.
<form [formGroup]="myForm" (ngSubmit)="submit()"> <h4>Form</h4> <hr> <app-items-array formArrayName="items" [itemsFormArray]="myForm.get('items')"> </app-items-array> <hr> <div class="form-group"> <input type="submit" class="form-control" value="Submit" [disabled]="myForm?.invalid"> </div> </form> <h6 class="mt-3">FormGroup Model (<code>myForm.value</code>)</h6> <div> <pre><code>{{ myForm?.value | json }}</code></pre> </div>
@Component({ selector: 'app-nested-form', templateUrl: './nested-form.component.html', styleUrls: ['./nested-form.component.css'] }) export class NestedFormComponent implements OnInit { myForm: FormGroup; constructor( private fb: FormBuilder ) {} ngOnInit() { // build the form model this.myForm = this.fb.group({ items: new FormArray([ new FormGroup({ name: new FormControl('aaa1', Validators.required), quantity: new FormControl(100) }), new FormGroup({ name: new FormControl('', Validators.required), quantity: new FormControl(100) }) ], ItemsValidators.minQuantitySum(300)) }) } submit() { console.log("Reactive Form submitted: ", this.myForm) } }
Расширим форму компонентом ItemFormControlComponent
Извлечем итем из FormArray
в отдельный компонент. Назовем его ItemFormControlComponent
. Передадим индекс и экземпляр FormGroup
как входящие свойства. FormGroup
создается функцией addItem()
в компоненте ItemsFormArrayComponent
.
Также будем эмитить наверх индекс FormGroup
, чтобы иметь возможность удалять компонент в родительской форме ((removed)="itemsFormArray.removeAt($event)"
).
<div class="form-group row" [formGroup]="item"> <div class="col-sm-6"> <label [attr.for]="'name'+index">Name</label> <input type="text" class="form-control" [attr.id]="'name'+index" formControlName="name"> </div> <div class="col-sm-5"> <label [attr.for]="'quantity'+index">Quantity</label> <input type="number" class="form-control" [attr.id]="'quantity'+index" formControlName="quantity"> </div> <div class="col-sm-1 py-1"> <button type="button" class="btn" (click)="removed.emit(index)">-</button> </div> </div>
@Component({ selector: 'app-item-control', templateUrl: './item-control.component.html', styleUrls: ['./item-control.component.css'] }) export class ItemControlComponent { @Input() public index: number; @Input() public item: FormGroup; @Output() public removed: EventEmitter<number> = new EventEmitter<number>(); }
Расширим форму компонентом ItemsFormArrayComponent
Второй шаг - извлечь массив итемов в свой собственный компонент (назовем его ItemsFormArrayComponent
). Передадим FormArrayas
как входящее свойство. Отметьте небольшое изменение по сравнению с предыдущим подходом: мы запишем formArrayName="items"
на рутовом компоненте:
<items-array formArrayName="items" [items]="myForm.get('items')">
Конечно, мы переиспользуем ItemFormControlComponent
из предыдущего шага.
<fieldset> <h6>Items</h6> <div *ngIf="itemsFormArray.hasError('minSum')"> Вы должны купить по крайней мере {{ itemsFormArray.getError('minSum') }}. </div> <app-item-control *ngFor="let item of itemsFormArray.controls; let i=index" [index]="i" [item]="item" (removed)="itemsFormArray.removeAt($event)"> </app-item-control> </fieldset> <button type="button" class="btn btn-link" (click)="addItem()">Add another item</button>
@Component({ selector: 'app-items-array', templateUrl: './items-array.component.html', styleUrls: ['./items-array.component.css'] }) export class ItemsArrayComponent { @Input() public itemsFormArray: FormArray; addItem() { this.itemsFormArray.push(new FormGroup({ name: new FormControl('aaa', Validators.required), quantity: new FormControl(100) })) } }
Три компонента и директивы
Давайте провиализируем. Красными выделены компоненты, белым директивы.
Как вы видите, экземпляры модели формы передаются от верхнего компонента далее вниз по дереву.
Резюме
Модель формы сконструирована при помощи FormControl
, FormArray
, FormGroup
. Директивы соединяют существующую модель формы внутри шаблона (реактивные формы).
Модель формы можеь быть проброшена из одного компанента в другой через входящие свойтсва. Эта техника позволяет создавать довольно утонченные и сложные формы, которые состоят из нескольких компонентов. Реактивные формы хорошо подходят для этой идеи, позволяя относительно лекго создавать вложенные формы.
Источник Создаем вложенные, реактивные формы
Комментарии: