Issue
I am currently able to edit all data from my update CRUD form except for the dynamic nested array (called ‘mitigations’) that only returns the first object on my form. I have 4 objects, but it’s only showing 1 out of 4, and I want the end user to be able to edit all of them through the same form they originally created. I also want them to be able to add new mitigations or remove existing ones as they can with the create CRUD form.
Please let me know what I’m missing. Thanks.
edit.component.ts
export class EditComponent implements OnInit {
getId: any;
updateForm: FormGroup;
constructor(
public formBuilder: FormBuilder,
private router: Router,
private ngZone: NgZone,
private activatedRoute: ActivatedRoute,
private crudService: CrudService
) {
this.getId = this.activatedRoute.snapshot.paramMap.get('id');
this.crudService.GetRisk(this.getId).subscribe(res => {
this.updateForm.setValue({
...
mitigations: res['mitigations']
});
});
this.updateForm = this.formBuilder.group({
...
mitigations: this.formBuilder.array([])
})
}
addMitigation() {
let control = <FormArray>this.updateForm.controls.mitigations;
control.push(
this.formBuilder.group({
mitigation_description: ['', Validators.compose([Validators.required, Validators.minLength(10)])],
mitigation_option: ['', Validators.required]
})
)
}
removeMitigation(index) {
let control = <FormArray>this.updateForm.controls.mitigations;
control.removeAt(index)
}
ngOnInit() {
let control = <FormArray>this.updateForm.controls.mitigations;
control.push(
this.formBuilder.group({
mitigation_description: ['', Validators.compose([Validators.required, Validators.minLength(10)])],
mitigation_option: ['', Validators.required]
})
)
}
onUpdate(): any {
this.crudService.updateRisk(this.getId, this.updateForm.value)
.subscribe(() => {
console.log('Data updated successfully!')
this.ngZone.run(() => this.router.navigateByUrl('/risk/details'))
}, (err) => {
console.log(err);
});
}
}
edit.component.html
<div class="card-body widget-body">
<form [formGroup]="updateForm" (ngSubmit)="onUpdate()">
<div formArrayName="mitigations">
<div *ngFor="let mitigation of updateForm.get('mitigations')['controls']; let i=index">
<div [formGroupName]="i">
<div class="form-group">
<label for="textarea">Mitigation {{i+1}} Description</label>
<textarea class="form-control form-control-sm checking-field" formControlName="mitigation_description" required></textarea>
<span class="help-block" *ngIf="mitigation.get('mitigation_description').touched">
<span class="text-danger" *ngIf="mitigation.get('mitigation_description').hasError('required')">Description is required</span>
<span class="text-danger" *ngIf="mitigation.get('mitigation_description').hasError('minlength')">Minimum of 10 characters</span>
</span>
</div>
<div class="form-group">
<label for="select">Mitigation {{i+1}} Option</label>
<select class="form-control form-control-sm checking-field" formControlName="mitigation_option">
<option>Accept</option>
<option>Transfer</option>
<option>Reduce</option>
<option>Avoid</option>
</select>
<span class="help-block text-danger" *ngIf="mitigation.get('mitigation_option').touched && mitigation.get('mitigation_option').hasError('required')">Option is required</span>
</div>
</div>
<div class="form-group">
<button type="button" class="btn-sm btn-main" (click)="addMitigation()">Add Mitigation</button>
<button [hidden]="i == 0" type="button" class="btn-sm btn-danger pull-right" (click)="removeMitigation(i)">Remove Mitigation {{i+1}}</button>
</div>
</div>
</div>
</form>
</div>
Solution
I got it working with the help of a developer. This is what the working constructor looks like:
constructor(
public formBuilder: FormBuilder,
private router: Router,
private ngZone: NgZone,
private activatedRoute: ActivatedRoute,
private crudService: CrudService
) {
this.getId = this.activatedRoute.snapshot.paramMap.get('id');
this.crudService.GetRisk(this.getId).subscribe(res => {
const mitigations = this.updateForm.get('mitigations') as FormArray;
while (mitigations.length) {
mitigations.removeAt(0);
}
this.updateForm.patchValue(res);
res.mitigations.forEach(mitigation =>
mitigations.push(this.formBuilder.group(mitigation)));
this.updateForm.setValue({
...
mitigations: res['mitigations']
});
});
this.updateForm = this.formBuilder.group({
...
mitigations: this.formBuilder.array([])
})
}