在Angular 2+中,如何对FormArray对象进行理想的排序?

16
我有一个formArray,其中包含多个表单组。我需要根据数组中每个表单组中存在的布尔字段动态排序该数组。
布尔字段是复选框,任何时候只能选中一个复选框(模拟单选按钮)。因此,当单击复选框时,我需要基于所选的复选框对formArray进行排序。
我知道文档建议不要干扰formArray中存在的AbstractControls[],那么动态排序数组的理想方式是什么?
我尝试过切片数组并将控件设置回formArray,但我一直收到错误“必须为名称为'primaryIndicator'的表单控件提供值。
const abstractControls = this.formArray.controls
          .slice()
          .sort((a, b) => {
            return (a as FormGroup).get('primaryIndicator').value ? -1 : (b as FormGroup).get('primaryIndicator').value ? 1 : 0;
          });
        this.formArray.setValue(abstractControls);

如果这不是正确的方法,那么解决这种情况的最佳方法是什么?
6个回答

16

我认为这不是最好的方法,但可以从表单数组中获取值,对其进行任何操作,并将其补丁回来。

var myArray = this.formArray.value;
//do sorting here with myArray.sort 
this.formArray.patchValue(myArray)

不要改变this.formArray的长度和架构。 patchValue只能修补值,如果它们具有相同的结构。


谢谢,我也尝试过这个方法,但好像不起作用。无论如何,我已经改变了我的实现方式,现在有两个循环,一个用于查找第一个要显示的指示器为true的元素,第二个循环用于所有为false的元素。这不是一种优雅的解决方案,但这是我能想到的最好的方法。希望Angular也可以在formArray上有一个排序谓词 :) - Adnan Mamajiwala
2
我在我的项目中也是这样使用的...但你说得对,在表单数组中进行排序应该是开箱即用的。你已经在Github上提出了问题吗? - Lorfme
2
如果FormArray包含另一个FormArray的FormGroup,那么可能会很棘手。如果不是所有后代FormArrays都相同,则修补程序将失败。是的,您已经提到了这一点,但对于更复杂的表单层次结构来说,重要的是不要忘记考虑子级,如果它们的长度也可能会变化。 - Simon_Weaver

3

它对我有效。我用一行代码做了类似的事情

这样做:this.names.patchValue(this.names.value.sort((a, b) => a.name.localeCompare(b.name)));


2

排序和过滤

  sortArray(array: Array<any>, prop: string): Array<any> {
    return array.sort((a, b) => {
      prop.split('.').forEach(p => {
        a = a[p];
        b = b[p];
      });

      return (a > b) ? 1 : ((b > a) ? -1 : 0);
    });
  }

然后进行调用。
const cartItemsFormArr = this.cartForm.get('cartItemsCtrls') as FormArray;


this.cartForm.controls['cartItemsCtrls'] = this._fb.array(
  this.sortArray(cartItemsFormArr.controls.filter(ctrl => !ctrl.value['isChecked']), 'value.idShoppingCartDetail'));

1

我已经有一个排序好的值数组,并使用lodash的_.sortBy方法,如下:

const orderedTitles: Array<string> = ['title1', 'title2', 'title3'];
const pagesFormArray: FormArray = (this.form.get('pages') as FormArray);
pagesFormArray.controls = _.sortBy(pagesFormArray.controls, (control) => {
  return _.indexOf(orderedTitles, control.value.title'
});

我使用 @Lorfme 的答案时遇到的问题是,我在扩展基本的 Angular 表单控件并在我的类上设置其他属性。就像这样:

class MyNewFormArray extends FormArray {
  private additionalStuff;

  constructor(formArgs, additionalStuff) {
    super(formArgs);
    this.additional = additionalStuff;
  }

  someMethod() {
    return this.additionalStuff;
  }
}

0
sortFormArray() {
let sortArray = this.formArray.value;
sortArray.sort((a, b) => {
  const A = a.primaryIndicator.toUpperCase();
  const B = b.primaryIndicator.toUpperCase();

  let comparison = 0;
  if (A > B) {
    comparison = 1;
  } else if (A < B) {
    comparison = -1;
  }
  return comparison;
});
this.appFormArrayData.setValue(sortArray);

}


0

最好清除之前的 FormArray,并用新排序的控件列表填充它,而不仅仅是在之前的控件顺序上执行值修补

updateForm(sortedList) {
  this.form.get('YOUR_KEY').clear();

  sortedList.forEach(entity => {
    this.form.get('YOUR_KEY').push(this.createFormGroup(entity));
  });
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接