在 Angular 2+ 中对 FormArray 对象进行排序的理想方法是啥?

Posted

技术标签:

【中文标题】在 Angular 2+ 中对 FormArray 对象进行排序的理想方法是啥?【英文标题】:What is the ideal way to sort a FormArray object in Angular 2+?在 Angular 2+ 中对 FormArray 对象进行排序的理想方法是什么? 【发布时间】:2018-08-16 07:34:48 【问题描述】:

我有一个由多个表单组组成的 formArray。我需要根据数组中每个表单组中存在的布尔字段对数组进行动态排序。

布尔字段是一个复选框,在任何给定时间点都只能选中一个复选框(模仿单选按钮)。因此,当单击复选框时,我需要根据所选的对 formArray 进行排序。

我知道文档建议不要弄乱 formArray 中的 AbstractControls[],那么动态排序数组的理想方法是什么?

我尝试对数组进行切片并将控件设置回 formArray,但我不断收到错误消息“必须为表单控件提供一个值,名称为:'primaryIndi​​cator'。

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);

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

【问题讨论】:

【参考方案1】:

我认为这不是最好的方法,但是从 formarray 中获取值,用它做任何你想做的事情并将它们修补回来。

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

不要更改 this.formArray 的长度和架构。 Patchvalue 只能对具有相同结构的值进行修补。

【讨论】:

谢谢,我也试过这个,好像不行。无论如何,我已经将我的实现更改为现在必须循环一个以查找指示符 true 作为要显示的第一个元素,第二个循环查找所有为 false 的元素。它不是一个优雅的解决方案,但这是我能想到的最好的解决方案。 Wish angular 在 formArray 上也有一个排序谓词:) 我在我的项目中使用它......但你是对的,formarrays 中的排序应该是开箱即用的。你在 github 上发过问题了吗? 如果 FormArray 包含一个 FormGroup 和另一个 FormArray,则可能会很棘手。如果并非所有后代 FormArray 都相同,则补丁将失败。是的,您已经提到了这一点,但是对于更复杂的表单层次结构来说,重要的是不要忘记考虑孩子们(如果他们也可以很长的话)。【参考方案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'));

【讨论】:

【参考方案3】:

我已经有一个排序值数组,并像这样使用 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;
  

【讨论】:

【参考方案4】:

它对我有用。我用单线做了这样的事情

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

【讨论】:

【参考方案5】:

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);

【讨论】:

以上是关于在 Angular 2+ 中对 FormArray 对象进行排序的理想方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章

Angular 2:从 FormArray 访问数据

angular FormArray用法指南

设置初始值Angular 2反应formarray

以反应形式设置 Angular 2 FormArray 值?

在 formArray Angular 中选择独立的选项

Kendo Grid for Angular 2 Reactive FormArray