I am trying to populate nested ReactiveForm
which is split into several child form components. Once the API request is completed I am able to populate parent form but cannot loop child FormArray
exactly to the count of child data. Below are the snippets from my code:
Edit View: edit.component.ts
@Component({
selector: 'app-edit',
templateUrl: './edit.component.html',
styleUrls: ['./edit.component.scss']
})
export class EditComponent implements OnInit {
public data: Service = new Service({
id: '',
title: '',
description: '',
service_extras: []
});
public routeParams: any = {};
constructor (
private route: ActivatedRoute,
private service: ServicesService
) { }
ngOnInit() {
this.setRouteParams();
}
setRouteParams() {
this.route.params.subscribe(params => {
this.routeParams = params;
// getting services using api call
this.getService(this.routeParams);
});
}
getService(params) {
this.service
.getService(params.id)
.subscribe((service: Service) => {
this.data = service;
});
}
}
I am requesting data in base edit.component.ts
component and passing the data received to the parent form component which is child of EditComponent
edit.component.html
<service-form [serviceFormData]="data"></service-form>
service-form.component.ts
@Component({
selector: 'service-form',
templateUrl: './service-form.component.html',
styleUrls: ['./service-form.component.scss']
})
export class ServiceFormComponent implements OnInit {
private _serviceFormData = new BehaviorSubject<Service>(null);
@Input()
set serviceFormData(value) {
this._serviceFormData.next(value);
}
get serviceFormData() {
return this._serviceFormData.getValue();
}
public service: Service;
public serviceForm: FormGroup;
constructor(
private fb: FormBuilder
) { }
ngOnInit() {
this.serviceForm = this.toFormGroup();
this._serviceFormData.subscribe(data => {
this.serviceForm.patchValue(data);
});
}
private toFormGroup(): FormGroup {
const formGroup = this.fb.group({
id: [ '' ],
title: [ '' ],
description: [ '' ]
});
return formGroup;
}
}
I have here receiving data with the help of @Input
var by subscribing to its changes and then patching value to the form, now everything works fine upto this as all the fields gets filled once the data is received. Problem is here below:
service-extra.component.ts
@Component({
selector: 'service-extra-form',
templateUrl: './service-extra.component.html',
styleUrls: ['./service-extra.component.scss']
})
export class ServiceExtraComponent implements OnInit {
private _extraFormData = new BehaviorSubject<ServiceExtra[]>([]);
@Input() serviceForm: FormGroup;
@Input()
set extraFormData(value: ServiceExtra[]) {
this._extraFormData.next(value);
}
get extraFormData() {
return this._extraFormData.getValue();
}
public extrasForm: FormGroup;
constructor(private fb: FormBuilder) { }
ngOnInit()
{
this.serviceForm.addControl('service_extras', new FormArray([]));
this._extraFormData.subscribe(data => {
this.addNew();
this.extras.patchValue(data);
});
}
private toFormGroup()
{
const formGroup = this.fb.group({
id: [''],
service_id: [''],
title: ['']
});
return formGroup;
}
public addNew()
{
this.extrasForm = this.toFormGroup(); (<FormArray>this.serviceForm.controls.service_extras).push(this.extrasForm);
}
public removeThis(i: number)
{
(<FormArray>this.serviceForm.controls.service_extras).removeAt(i);
}
get extras(): FormArray {
return this.serviceForm.get('service_extras') as FormArray;
}
}
Above ngOnInit
code does nothing but adds the single extras form (even if there are two records) and populate that form, this case is same even if I remove subscribe part and only use this.addNew()
. How do I know how many records are there for ServiceExtras
so that I can add that much FormGroups
to FormArray
.
Edit 1
Stackblitz Demo
Edit 2
Issue is if there are two records coming from API for service extra then I am not able to generate two FormGroups
and populate them with data, Because at the time of rendering I cannot detect how many records are coming for service extras from API.