我正在建立反应式,如下图所示-
如图所示,每个文件(在代码中称为附件)中都有多个议程。议程可以添加,更新和删除
buildForms() {
this.agendaForms = this.formBuilder.group({
attachements: this.formBuilder.array([
])
});
从Web服务获取表单数据,并以这种方式创建表单模型-
data => {
this.submission = data;
// New blank agenda for all attachements
if (
!isNullOrUndefined(this.submission) &&
!isNullOrUndefined(this.submission.attachments)
) {
this.submission.attachments.forEach(attachment => {
const agenda = new NLAgenda();
agenda.dwgNo = attachment.filename;
agenda.dWGNo = attachment.filename;
this.submission.agendas.push(agenda);
if (!isNullOrUndefined(attachment)) {
attachment.agendas = this.getAgendasForAttachment(attachment);
if (!isNullOrUndefined(attachment.agendas)) {
this.attachmentFormArray = this.agendaForms.controls
.attachements as FormArray;
this.attachmentFormArray.push(
this.createAttachmentAgendasControl(attachment.agendas)
);
}
}
});
}
}
模板看起来像这样
<form [formGroup]="agendaForms">
<div formArrayName="attachements">
<div *ngFor="let attachmentFormGroup of attachmentFormArray.controls;
let attachmentId = index">
<!-- Attachment header-->
<div>
<!-- File Name-->
<div>
{{ submission.attachments[attachmentId].filename }}
</div>
<!-- Action Buttons-->
<div>
<input type="button" value="Link To"/>
</div>
</div>
<!-- Agendas -->
<div formGroupName="{{ attachmentId }}">
<div formArrayName="agendas">
<div *ngFor="let agendaFormGroup of attachmentFormGroup.controls.agendas.controls;
let agendaId = index">
<div formGroupName="{{ agendaId }}" >
<mat-form-field>
<input
type="text"
id="project"
placeholder="Sheet No."
formControlName="sheetNumber"
matInput
/>
<!-- <mat-error>{{ getErrorMessage(f.project) }}</mat-error> -->
</mat-form-field>
<mat-form-field>
<input
type="text"
id="project"
placeholder="Title"
formControlName="title"
matInput
/>
</mat-form-field>
<mat-form-field>
<input
type="text"
id="project"
placeholder="Description"
formControlName="description"
matInput
/>
</mat-form-field>
<div>
<a
matTooltip="Add Agenda"
aria-label="Add Agenda"
(click)="
createOrUpdateAgenda(
submission.attachments[attachmentId].agendas[agendaId],
attachmentId,
agendaId
)">
<i class="fa fa-check"></i>
</a>
<a
*ngIf="submission.attachments[attachmentId].agendas[agendaId].created != null && submission.attachments[attachmentId].agendas[agendaId].created != undefined"
matTooltip="Delete Agenda"
aria-label="Delete Agenda"
(click)="deleteAgenda(submission.attachments[attachmentId].agendas[agendaId])">
<i class="fa fa-remove"></i>
</a>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</form>
问题: 每当添加或更新议程时,我都会从服务器中获取提交对象数据,以显示文件和议程的更新状态,提交对象发生更改,并在控制台中显示错误,例如“无法读取未定义的属性'agendas'”,因为旧对象处于新提交对象位置因新增或删除而更改
我相信我只需要使用一个数组(FormArray)而不是两个数组(Form array和Submission Object)来构建模板,否则如果一个更改直到其他更改控制台将引发错误。但是如何仅使用FormArray,我在Submission Object中有一些数据?有没有办法用FormArray绑定提交对象?
我很累https://github.com/angular/angular/issues/13845,但是由于我使用表单构建而没有成功,并且不知道如何使用表单构建器来完成此技巧
答案 0 :(得分:0)
如果您首先考虑所获得的数据,则更容易。我想你会得到像
[{filename:..,agenda:[
{sheetNumber:..,title:...,description...},
{sheetNumber:..,title:...,description...}
...
]
},
{filename:..,agenda:[
{sheetNumber:..,title:...,description...},
{sheetNumber:..,title:...,description...}
...
]
}
....
]
您看到您有一个FormArray(一系列FormGroup),它具有两个属性“文件名”和“议程”(议程是一个新的FormArray)
将变量声明为formArray
form: FormArray
并创建两个函数。
createItemData(data):FormGroup
{
data=data|| {} as dataI;
return new FormGroup(
{
filename:new FormControl(data.filename),
agenda:new FormArray(data.agenda && data.agenda.length?
data.agenda.map(agenda=>this.createAgendaSheet(agenda)):
[])
}
)
}
createAgendaSheet(data):FormGroup{
data=data|| {} as agendaI;
return new FormGroup(
{
sheetNumber:new FormControl(data.sheetNumber),
title:new FormControl(data.title),
description:new FormControl(data.description),
}
)
}
查看此函数如何创建数组的元素。我使用接下来的两个界面来帮助我创建表单
export interface agendaI {
sheetNumber: number,
title: string,
desription: string
}
export interface dataI {
filename: string,
agenda: agendaI[]
}
好吧,创建表单时要小心:
<button (click)="addAgenda()">Add agenda</button>
<form *ngIf="form" [formGroup]="form">
<!--form is a FormArray, so form.controls will be formGroup-->
<div *ngFor="let control of form.controls;let i=index">
<!--in this form group...-->
<div [formGroup]="control">
<!--we have a fromControl "filename"-->
<input formControlName="filename"/><button (click)="add(i)">add</button>
<!--and a FormArray "agenda"--->
<div formArrayName="agenda">
<div *ngFor="let c of control.get('agenda').controls;let j=index" >
<div [formGroupName]="j">
<input formControlName="sheetNumber">
<input formControlName="title">
<input formControlName="description">
<button (click)="delete(i,j)">delete</button>
</div>
</div>
</div>
</div>
</div>
</form>
好吧,最后一步是创建函数add,delete和addAgenda
addAgenda()
{
this.form.push(this.createItemData(null))
}
add(i)
{
(this.form.at(i).get('agenda') as FormArray).push(this.createAgendaSheet(null))
}
delete(i,j)
{
(this.form.at(i).get('agenda') as FormArray).removeAt(j)
}
然后,在ngOnInit中创建表单(我使用了常量“数据”)
ngOnInit() {
this.form=new FormArray(data.map(d=>this.createItemData(d)));
}
您可以在stackblitz中看到“丑陋”的结果