I have an input where the user can enter a country and a city separated by a comma to a list of countries and cities. The list should then be displayed in a way that each city is listed under its country group.
I'm struggling to find the right way to construct my form.
form = this.fb.group({
newEntry: [],
cityToFind: [],
citiesList: this.fb.array([]),
});
get citiesListForm(): FormArray {
return this.form.get('citiesList') as FormArray;
}
get searchInput(): FormControl {
return this.form.get('cityToFind') as FormControl;
}
get newEntryFormControl(): FormControl {
return this.form.get('newEntry') as FormControl;
}
getCountryFormArray(country: string): FormArray {
return this.citiesListForm.get(country) as FormArray;
}
addCountrySection(country: string): void {
this.citiesListForm.push(
this.fb.group({
[country]: this.fb.array([]),
}),
);
}
addCity(country: string, city: string): void {
this.getCountryFormArray(prefix).push(
this.fb.control(nr),
);
}
ngOnInit(): void {
this.addCountrySection('USA');
this.addCountrySection('DE');
this.addCity('DE', 'Berlin');
console.log(this.getCountryFormArray('DE')); // This is returning null
}
Is the form structure correct? Can someone provide me with an example how to write the template.
The major problem with your approach is that you are mixing FormArrays
and FormGroups
.
Consider your desired structure
{
citiesList: [ // <--------FormArray
{ de: ["Berlin"] }, // <--------FormGroup
{ usa: [] }
]
}
So If I would like to access the "de" element I would need to do something like
form[citiesList][0].de
So for the reactive form this would be form.get("citiesList").controls[0].get("de")
I have illustrated this in This stackblitz demo
This would work but I think a better approach would be to simply remove the outer array and have below
{
citiesList: {
de: ["Berlin"],
usa: []
}
}
With this you will be adding controls with country as property.
Another approach to consider may be to use the formArray like below
{
citiesList: [
{ country: "DE", cities: ["Berlin"] },
{ country: "USA", cities: [] },
}
]
}