我有一个输入,用户可以输入一个国家和一个城市,用逗号分隔到一个国家和城市的列表。然后,应以将每个城市列在其国家组下的方式显示该列表。
我很难找到正确的方法来构造我的表格。
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
}表格结构正确吗?有人能给我提供一个如何编写模板的例子吗?
发布于 2021-09-02 12:31:17
您的方法的主要问题是您正在混合FormArrays和FormGroups。
考虑一下您想要的结构
{
citiesList: [ // <--------FormArray
{ de: ["Berlin"] }, // <--------FormGroup
{ usa: [] }
]
}因此,如果我想访问"de“元素,我需要执行以下操作
form[citiesList][0].de因此,对于反应形式,这将是form.get("citiesList").controls[0].get("de")
我已经在这个stackblitz演示中说明了这一点
这是可行的,但我认为更好的方法是简单地删除外部数组并使其具有以下内容
{
citiesList: {
de: ["Berlin"],
usa: []
}
}这样,您将添加以国家为属性的控件。
另一种需要考虑的方法可能是使用formArray,如下所示
{
citiesList: [
{ country: "DE", cities: ["Berlin"] },
{ country: "USA", cities: [] },
}
]
}发布于 2021-09-02 13:37:31
FormArray是FormGroup的一个变种,但是区别在于,当使用FormGroup时,数据被序列化为Array而不是object。当您不知道需要多少控件时(当您创建动态表单时),这可能很有用。
FormGroup将每个子FormControl的值聚合到一个对象中,并以每个控件名称作为键。它通过减少其子级的状态值来计算其状态。例如,如果组中的某个控件无效,则整个组将变得无效。FormArray将每个子FormControl的值聚合到一个数组中。它通过减少其子级的状态值来计算其状态。例如,如果FormArray中的一个控件无效,整个数组就无效。
下面我添加了代码片段和注释,以帮助您了解正在发生的事情。
export class AppComponent {
form: FormGroup = this.fb.group({
newEntry: [],
cityToFind: [],
citiesList: this.fb.array([])
});
constructor(private fb: FormBuilder) {}
// Get your cityToFind FormArray
get citiesListForm(): FormArray {
return this.form.get('citiesList') as FormArray;
}
// Get your cityToFind FormControl
get searchInput(): FormControl {
return this.form.get('cityToFind') as FormControl;
}
// Get your newEntry FormControl
get newEntryFormControl(): FormControl {
return this.form.get('newEntry') as FormControl;
}
// Get the Country FormArray
getCountryFormArray(country: string): FormArray {
const index = this.citiesListForm.controls.findIndex(control => control.get(country));
return this.citiesListForm.controls[index].get(country) as FormArray;
}
// Check if Country Exists
doesCountryExist(country: string): Boolean {
return this.citiesListForm.controls.filter(x => x.get(country)).length === 0 ? false : true;
}
// Add the Country to citiesList Form
addCountrySection(country: string): void {
if (!this.doesCountryExist(country)) {
this.citiesListForm.push(
this.fb.group({
[country]: this.fb.array([])
})
);
}
}
// Add either country or country and city
addCountryAndOrCity(country: string, city: string = null) {
if (!this.doesCountryExist(country)) {
this.addCountrySection(country)
}
if(city !== null){
this.getCountryFormArray(country).push(this.fb.control(city))
}
}
ngOnInit(): void {
// Add just countries
this.addCountryAndOrCity('USA');
this.addCountryAndOrCity('DE');
// Add countries and cities
this.addCountryAndOrCity('DE', 'Berlin');
this.addCountryAndOrCity('DE', 'New City 1');
this.addCountryAndOrCity('USA', 'New City 2');
this.addCountryAndOrCity('GB', 'leicester');
this.addCountryAndOrCity('GB', 'london');
this.addCountryAndOrCity('GB', 'Manchester');
console.log('DE has ' + (this.getCountryFormArray('DE').length) + ' cities');
// DE has 2 cities
console.log('GB has ' + (this.getCountryFormArray('GB').length) + ' cities');
// GB has 3 cities
console.log('USA has ' + (this.getCountryFormArray('USA').length) + ' cities');
// USA has 1 cities
}
}我同意欧文·凯尔文的观点,他说,你把这两者和他提到的结构混合在一起,在我看来更干净,也不那么让人困惑。
https://stackoverflow.com/questions/68935531
复制相似问题