I am building reactive form like the pic shown below-
As shown in pic every file (referred as attachment in code) have multiple agendas in them. Agendas could be added, updated and deleted
buildForms() {
this.agendaForms = this.formBuilder.group({
attachements: this.formBuilder.array([
])
});
Form data is fetched from webservice and form model is created this way-
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)
);
}
}
});
}
}
Templates look something like this
<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>
Problem: Whenever agendas are added or updated I refetch submission object data from server to show updated state of files and agendas, submission object changes and gives errors in console like "Cannot read property 'agendas' of undefined" since in new submission object position of old objects is changed due to new addition or deletion
I believe I need to build template only using one array (FormArray) and not two arrays (Form array and Submission Object), else if one changes till other changes console will throw error. But how to use only FormArray, I have some data in Submission Object? Is there a way to bind submission object with FormArray?
I tired https://github.com/angular/angular/issues/13845 but didn't succeed as I am using form build and didn't know how to do this trick with form builder
