Search code examples
actionscript-3sortingdatagridmxml

Reuse sortCompareFunction across DataGridColumns in AS3


I put together a DataGrid using the following functions

 public function get dataGridColumns():Array {
    var dataGridColumnArray:Array = [];
    dataGridColumnArray.push(createDataGridColumn(col1, "field1", 0.17, sortStrings));
    dataGridColumnArray.push(createDataGridColumn(col2, "field2", 0.17, sortStrings));
    dataGridColumnArray.push(createDataGridColumn(col3, "field3", 0.17, sortStrings));
    return dataGridColumnArray;
}

private static function createDataGridColumn(columnName:String, dataField:String, width:Number,sortCompareFunction:Function = null):DataGridColumn {
    var column:DataGridColumn = new DataGridColumn(columnName);
    column.dataField = dataField;
    column.width = width;
    column.sortCompareFunction = sortCompareFunction;
    return column
}

private function sortStrings(a:Object, b:Object, fields:Array = null):int{
    if(a.toString().toLowerCase() > b.toString().toLowerCase()){
        return 1;
    }else if(a.toString().toLowerCase() < b.toString().toLowerCase()){
        return -1;
    }else{
        return 0;
    }
}

Since my dataProvider is an array of data objects I run into the problem that a and b in the sort function are objects, and I want to somehow pass the data field (column title) into the sort so I can check the correct object property all using one sort function so it would look something like:

private function sortStrings(a:Object, b:Object, field:String):int{
    if(a.field.toLowerCase() > b.field.toString().toLowerCase()){
        return 1;
    }else if(a.field.toString().toLowerCase() < b.field.toString().toLowerCase()){
        return -1;
    }else{
        return 0;
    }
}

I have not figured out a good way to do this yet, and worst case scenario I have 6 extremely similar sort functions.


Solution

  • you can make a comparators factory function, which will return closures, enclosing the field name:

    private function createComparatorFor(field:String):Function {
        return function (a:Object, b:Object, fields:Array = null):int{
            const aField:String = a[field].toString().toLowerCase();
            const bField:String = b[field].toString().toLowerCase();
    
            if (aField > bField) {
                return 1;
            }
    
            if (aField < bField) {
                return -1;
            }
    
            return 0;
        }
    }
    

    and use it like this:

    dataGridColumnArray.push(createDataGridColumn(
        col1, "field1", 0.17, createComparatorFor("field1")));
    

    untested, but should work