问题
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 ?
回答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.
回答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'));
回答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;
}
}
回答4:
It worked for me. I did something like this with a one-liner
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);
}
来源:https://stackoverflow.com/questions/49164800/what-is-the-ideal-way-to-sort-a-formarray-object-in-angular-2