What is the ideal way to sort a FormArray object in Angular 2+?

11,243

Solution 1

I do not think it would be the best way, but get the values from formarray, do whatever you want with it and patch them back.

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

Do not change the length and schema of this.formArray. Patchvalue can only patch values, if they have same structure.

Solution 2

Sorting and Filtering

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

then the call

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

Solution 3

I already had an array of sorted values and use lodash's _.sortBy method like this:

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

The trouble I had with using @Lorfme's answer, was that I was extending the base Angular form controls and setting additional properties on my classes. Like this:

class MyNewFormArray extends FormArray {
  private additionalStuff;

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

  someMethod() {
    return this.additionalStuff;
  }
}
Share:
11,243

Related videos on Youtube

Adnan Mamajiwala
Author by

Adnan Mamajiwala

Currently working for mortgage insurance company and providing java based IT solutions for their business problems. I have been a java developer for the past 11 years. I am passionate about learning new technologies and take pride in writing high quality code.

Updated on July 13, 2022

Comments

  • Adnan Mamajiwala
    Adnan Mamajiwala almost 2 years

    I have a formArray which consist of multiple form groups. I need to sort the array dynamically based on a boolean field present in each of the form group in the array.

    The boolean field is a checkbox and at any given point of time only one checkbox can be checked (mimics radio button). So when a checkbox is clicked I need to sort the formArray based on the one that is selected.

    I know the documentation suggests not to mess with the AbstractControls[] present in the formArray, so what would be the ideal way to dynamically sort the array ?

    I have tried to slice the array and set the controls back into the formArray but I keep getting an error "Must supply a value for form control with name: '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);
    

    If this is not the right way, what would be the best approach to solve such a scenario ?

  • Adnan Mamajiwala
    Adnan Mamajiwala about 6 years
    thanks, i did try it this too, it doesn't seem to work. Anyways I have changed my implementation to now have to loops one to look for the indicator true as the first element to be displayed, second loop for all the elements that are false. Its not an elegant solution, but thats the best I could come up with. Wish angular had a sorting predicate on the formArray too :)
  • Lorfme
    Lorfme about 6 years
    I use it so in my projects.... But you are right, sorting in formarrays should be avaiable out of the box. Did you made an issue on github already?
  • aruno
    aruno over 2 years
    could be tricky if the FormArray contains a FormGroup with yet another FormArray. The patch will fail if not all descendant FormArrays are the same. Yes you already mentioned this, but it's important for more complex form hierarchies not to forget to consider the children if they can very in length too.