Вложенные массивы в Angular 2 реактивные формы?
Я использовал следующий учебник для создания реактивных форм в Angular 2, и он работает хорошо.
https://scotch.io/tutorials/how-to-build-nested-model-driven-forms-in-angular-2
Тем не менее, я сейчас пытаюсь добавить массив в массиве. Используя описанное выше руководство, я создал форму "Организация", которая может содержать массив групп "Контакты". Но я не могу успешно адаптировать настройки, чтобы каждая группа "Контакты" содержала массив групп "Электронная почта".
Я не смог найти учебник или пример, который охватывает это и был бы благодарен за любые указатели.
1 ответ
Используя описанное выше руководство, я создал форму "Организация", которая может содержать массив групп "Контакты". Но я не могу успешно адаптировать настройки, чтобы каждая группа "Контакты" содержала массив групп "Электронная почта".
Учебник выше дает вам все, что вам нужно.
Я полагаю, вы хотите структуру, как это.
Для начала нужен какой-то компонент (AppComponent
в моем случае) где вы объявляете root FormGroup
, Я назвал это trustForm
ниже.
app.component.ts
export class AppComponent {
trustForm: FormGroup;
constructor(private fb: FormBuilder) { }
ngOnInit() {
this.trustForm = this.fb.group({
name: '',
contracts: this.fb.array([])
});
this.addContract();
}
initContract() {
return this.fb.group({
name: '',
emails: this.fb.array([])
});
}
addContract() {
const contractArray = <FormArray>this.trustForm.controls['contracts'];
const newContract = this.initContract();
contractArray.push(newContract);
}
removeContract(idx: number) {
const contractsArray = <FormArray>this.trustForm.controls['contracts'];
contractsArray.removeAt(idx);
}
}
В этом компоненте у вас также есть несколько методов, которые помогут вам манипулировать первым уровнем FormArray
- contracts
app.component.html
<div class="container">
<form [formGroup]="trustForm">
<h3>Add trust</h3>
<div class="form-group">
<label>Name</label>
<input type="text" class="form-control" formControlName="name">
</div>
<!--contracts-->
<div formArrayName="contracts">
<div *ngFor="let contract of trustForm.controls.contracts.controls; let i=index" class="panel panel-default">
<div class="panel-heading">
<span>Contract {{i + 1}}</span>
<span class="glyphicon glyphicon-remove pull-right" *ngIf="trustForm.controls.contracts.controls.length > 1" (click)="removeContract(i)"></span>
</div>
<div class="panel-body" [formGroupName]="i">
<contract [group]="trustForm.controls.contracts.controls[i]"></contract>
</div>
</div>
</div>
<div class="margin-20">
<button (click)="addContract()" class="btn btn-primary">
Add another contract +
</button>
</div>
</form>
<h5>Details</h5>
<pre>{{ trustForm.value | json }}</pre>
</div>
Существует не отличается от корневого HTML из учебника, кроме разных FormArray
название.
Затем вам нужно построить компонент контракта, который будет похож на AppComponent
contract.component.ts
export class ContractComponent {
@Input('group') contractGroup: FormGroup;
constructor(private fb: FormBuilder) { }
addEmail() {
const emailArray = <FormArray>this.contractGroup.controls['emails'];
const newEmail = this.initEmail();
emailArray.push(newEmail);
}
removeEmail(idx: number) {
const emailArray = <FormArray>this.contractGroup.controls['emails'];
emailArray.removeAt(idx);
}
initEmail() {
return this.fb.group({
text: ''
});
}
}
contract.component.html
<div [formGroup]="contractGroup">
<div class="form-group">
<label>Name</label>
<input type="text" class="form-control" formControlName="name">
</div>
<!--emails-->
<div formArrayName="emails">
<div *ngFor="let email of contractGroup.controls.emails.controls; let i=index" class="panel panel-default">
<div class="panel-heading">
<span>Email {{i + 1}}</span>
<span class="glyphicon glyphicon-remove pull-right" *ngIf="contractGroup.controls.emails.controls.length > 1" (click)="removeEmail(i)"></span>
</div>
<div class="panel-body" [formGroupName]="i">
<email [group]="contractGroup.controls.emails.controls[i]"></email>
</div>
</div>
</div>
<div class="margin-20">
<button (click)="addEmail()" class="btn btn-primary">
Add another email +
</button>
</div>
</div>
Как видите, мы просто заменим contracts
в emails
FormArray
и мы также проходим FormGroup
отправить компонент по электронной почте
И, наконец, вам нужно будет только заполнить EmailComponent
с желаемыми полями.
email.component.ts
export class EmailComponent {
@Input('group') emailGroup: FormGroup;
}
email.component.html
<div [formGroup]="emailGroup">
<div class="form-group">
<label>Text</label>
<input type="text" class="form-control" formControlName="text">
</div>
</div>
Завершенную версию вы можете найти на Plunker.
Если вы думаете, что это решение не кажется правильным, потому что родительский компонент содержит описание дочернего компонента, например initContract
а также initEmails
Вы можете взглянуть на более сложный
Пример плунжера
где каждый компонент отвечает за свою функциональность.
Если вы ищете решение для шаблонно-управляемых форм, прочитайте эту статью: