如何使用可变长度更新FormArray值

问题描述 投票:1回答:2

如果在FormArray为空时尝试设置FormArray值:

const array1 = new FormArray([]);
array1.setValue(['']);

我收到此错误:

尚未向该数组注册任何表单控件。如果您使用的是ngModel,则可能要检查下一个勾号

如果在1时加2,

const array2 = new FormArray([new FormControl('')]);
array2.setValue(['', '']);

我收到以下错误:

在索引1处找不到表单控件

如果我尝试将2设置为1,则

const array3 = new FormArray([new FormControl(''), new FormControl('')]);
array3.setValue(['']);

我收到以下错误:

必须在索引:1处提供用于表单控制的值。

问题:如何编写一个可以用任意长度的列表更新表单数组的值的函数?

StackBlitzhttps://stackblitz.com/edit/angular-wduzv9?file=src/app/app.component.ts

* edit我了解可以使用push()at()removeAt(0)方法。我在寻找通用功能。它可以使用您想要的任何方法。

angular typescript angular-reactive-forms
2个回答
0
投票

您可以初始化一个空的formArray,然后添加控件,然后设置值,


const arr = new FormArray([]);

const a = new FormControl('a', []);
const b = new FormControl('b', []);
const c = new FormControl('c', []);

arr.push(a);
arr.push(b);
arr.push(c);

console.log(arr.value);   // ["a", "b", "c"] 
// arr.setValue([0]);

console.log(arr) 
arr.controls[0].setValue('xxx')

console.log(arr.value);   // "xxx", "b", "c"

0
投票

问题是,在不知道要在新索引的AbstractControl中使用哪种类型的FormArray的情况下,无法在新键或索引处添加新值。

任何解决方案都必须考虑到该索引应该是FormControlFormGroup还是FormArray,因此我在toSubControl函数中提供了setFormArrayValue参数。 (我还提供了一些示例值来提供给此参数。)

我选择删除所有项目,然后为每个值添加新控件。试图保留已经存在的控件会产生一些奇怪的行为。

这是我想出的解决方案:

export function setFormArrayValue<T>(
    array: FormArray,
    values: T[],
    toSubControl: (values: T) => AbstractControl = toFormControl
) {
    while (array.length) {
        array.removeAt(0);
    }
    values
        .map(toSubControl)
        .forEach(function(control) {
            array.push(control);
        });
    return array;
}

function toFormControl(value) {
    return new FormControl(value)
}

function toFormGroup(value) {
    const fields = Object.entries(value).reduce(function(hash, [key, value]) {
        hash[key] = new FormControl(value);
        return hash;
    }, {})
    return new FormGroup(fields);
}

function toFormGroup(value) {
    const fields = Object.entries(value).reduce(function(list, [key, value]) {
        return list.concat([new FormControl(value)]);
    }, [])
    return new FormGroup(fields);
}
© www.soinside.com 2019 - 2024. All rights reserved.