Sorting and the DataGrid component

Another Tuesday LiveDocs day! The following example continues the theme of DataGrids and sorting.

The following example sorts columns either numerically or alphabetically. By default columns are sorted alphanumerically, so if you had a DataGrid with “1, 213, 11, 7” it would sort as “1,11,213,7”. By writing a custom sorting function that uses Array.sortOn, you can sort the dataProvider yourself using a numeric or text sort (even sort text as case insensitive).

1. Make sure you have DataGrid in Library
2. Add following ActionScript to frame 1 of the Timeline:

import mx.controls.gridclasses.DataGridColumn;
var my_dp:Array = new Array({name:’Grissom, M.’, avg:0.279}, {name:’Bonds, B.’, avg:0.362}, {name:’Cruz, D.’, avg:0.292}, {name:’Snow, J.’, avg:0.327});
var dg = this.createClassObject(mx.controls.DataGrid, “my_dg”, 999, {dataProvider:my_dp});
dg.setSize(240, 180);
var name_dgc:DataGridColumn = new DataGridColumn(“name”);
name_dgc.headerText = “Name:”;
name_dgc.width = 160;
dg.addColumn(name_dgc);
var avg_dgc:DataGridColumn = new DataGridColumn(“avg”);
avg_dgc.headerText = “Avg:”;
avg_dgc.width = 60;
dg.addColumn(avg_dgc);
//
var myListener:Object = new Object();
myListener.headerRelease = function(evt:Object) {
var sortOrder:String = evt.target.sortDirection;
var sortColumn:String = evt.target.columnNames[evt.columnIndex];
switch (sortColumn) {
case ‘name’ :
sortArray(my_dp, sortColumn, “TEXTNOCASE”, sortOrder);
break;
case ‘avg’ :
sortArray(my_dp, sortColumn, “NUMERIC”, sortOrder);
break;
}
};
my_dg.addEventListener(“headerRelease”, myListener);
//
function sortArray(my_array:Array, sortColumn:String, sortType:String, sortOrder:String) {
var sortOptions:Number = 0;
switch (sortType.toUpperCase()) {
case ‘NUMERIC’ :
sortOptions |= Array.NUMERIC;
break;
case ‘TEXTNOCASE’ :
sortOptions |= Array.CASEINSENSITIVE;
break;
}
if (sortOrder.toUpperCase() == ‘DESC’) {
sortOptions |= Array.DESCENDING;
}
my_array.sortOn(sortColumn, sortOptions);
}

3. Format the code (press the Auto Format button).
4. Test.

22 Responses to Sorting and the DataGrid component

  1. Hey Jen,How do you preselect a row in a Datagrid, from previously entered data or from another object?

  2. That wasn’t very clear.. I am sorry.What I meant was that I have some data in a datagrid that I want to have one of the rows preselected.Wait.. Maybe a drop-down combo box would be better..Thanks.Micah

  3. jdehaan says:

    Hi Micah,Try this:my_dg.dataProvider = [{num:1}, {num:213}, {num:11}, {num:7}];my_dg.selectedIndex = 1;This code preselects the second row in the DataGrid (0 based, so the second row).If you want to pre-select multiple rows, you have to make sure that the multipleSelection property is set to true first.my_dg.dataProvider = [{num:1}, {num:213}, {num:11}, {num:7}];my_dg.multipleSelection = true;my_dg.selectedIndices = [1, 2];Hope that helps,Jen.

  4. Micah says:

    How about preselecting based on one of the VALUES in that list. I am having trouble getting that accomplished.Thanks mucho appreociated.Micah

  5. jdehaan says:

    Sure — the following selects rows based on a value in the DataGrid.my_dg.dataProvider = [{num:1}, {num:210}, {num:11}, {num:7}];my_dg.multipleSelection = true;my_dg.selectedIndices = selectOddNumbers();function selectOddNumbers():Array {var temp_array:Array = my_dg.dataProvider;var return_array:Array = new Array();for (var i = 0; i

  6. nig says:

    Nice example! That sortDirection property really should have been public to start with. It’s worth pointing out that this example makes the correct choice in using Array.sortOn rather than Array.sort (and a comparison function) – Array.sortOn is an order of magnitude faster than using that comparison function. It’s kind of why we didn’t offer a dGcolumn.sortFunction property per column, to avoid people trying. It would have maybe made more sense to add a sortOptions property for the column instead. Oh well.

  7. peter says:

    I really wish that there was a way to easily define whether a column is text or numeric. I figure there has to be a simpler way to sort columns than the method listed above (no offense, jan).Or if not, any chance that somebody at MM can add that in the next version? (crosses fingers)

  8. cvb says:

    I guess the sort by number will work for a date field as well in that a date is really a number.Correct?

  9. czeren says:

    Hi jen, maybe this is not the right place to write this but…about your Data for Designers: Connecting to Data in Flash Using Data Wizards: I worked with your samples it works great..however when I put the datagrid component and the xml connector in a movie I can not see my data from the xml?I hope you can answer me

  10. frank bradshaw says:

    Hi Jen – I tried your sorting code with my dataprovider (created from an array) and datagrid, but the columns still sort incorrectly, ie 78 comes after 120 etchelp!regardsfrank

  11. frank bradshaw says:

    Hi again – your code works fine; but this is my code: function fillMebersGrid(records:String):Void {var tempRecords:Array = new Array();tempRecords = records.split(rowDelimiter);for (var i = 0; i var tempArr:Array = new Array();var tempObj:Object = new Object();tempArr = tempRecords[i].split(fieldDelimiter);for (var j = 0; j tempObj[tableFields[j]] = tempArr[j];}myDataprovider.push(tempObj);}members_dg.dataProvider = myDataprovider;}myDataprovider is still an array here, so in theory your code should work with mine….any thoughts or suggestions?cheersfrank

  12. Zac says:

    1 month on so not sure if anyone cares, i had the same problem is frank above. The functions (correct values passed etc) were working but the grid still wasnt being sorted properley.Im thinking the problem was related to the way the grid is being dynamically populated.I changed:my_dp.push(rowObj);to:my_dp.addItem(rowObj);And any column that was numeric i used the Number() function when adding to the rowObj.Quirky little solution but it worked!

  13. alfred says:

    I added a line to make the datagrid ediable:dg.editable = true;After that, the sorting doesn’t work right anymore. Numbers are sorted like strings.How can I contact jdehaan?

  14. peter says:

    Alfred, where did you put that line of code? I used the code directly from this page and set the “dg.editable = true;” on line 5 (but anything after line 3 should work) and it worked like a charm.

  15. alfred says:

    I place it below line 5. Even now that I’ve moved it to line 5, it doesn’t work once I type my own values.I’m using the FIRST example code on top, and nothing else.Try this:Avg:520510010112The sorting isn’t right. Can you please check?Running on FlashMX 2004 ver 7.2

  16. peter says:

    Alfred, yeah, that seems very weird. The batting averages are numbers, yet, after they’ve been edited, they seemingly change to string datatypes (which I guess makes sense, but is still buggy since you’d expect a numeric sort to try to convert it back to numbers).I added this code to the sortArray function (right above the my_array.sortOn(…) bit):var i:Number;for (i=0 ;i<my_array.length; i++ ) {   trace(i+”: “+typeof(my_array[i][sortColumn]));}If you test your Flash document in the authoring environment, you should see 0..3 are all numbers. Now, change 101 to 1010 and it should be a mix of numbers and strings. I’m guessing you’ll have to modify the code to convert from strings back to numbers. Not sure of the most efficient way, but seemingly the following code works:function sortArray(my_array:Array, sortColumn:String, sortType:String, sortOrder:String) {  var sortOptions:Number = 0;  switch (sortType.toUpperCase()) {  case ‘NUMERIC’ :    var i:Number;    for (i=0; i<my_array.length; i++) {      my_array[i][sortColumn] = Number(my_array[i][sortColumn]);    }    sortOptions |= Array.NUMERIC;    break;  case ‘TEXTNOCASE’ :…

  17. peter says:

    Actually, this is another cool little trick (and probably a lot more efficient than my attempt at re-casting every row of the DataGrid to the Number data type.You could create an event listener for the “cellEdit” event, which just casts the changed cell from the String back to a Number.Code ahoy! Add this code around line 15 or something, or anywhere around the headerRelease event listener code:// ———-myListener.cellEdit = function(evt:Object) {   var columnName:String = evt.target.columnNames[evt.columnIndex];   var cell:Object = evt.target.dataProvider[evt.itemIndex];   switch (columnName.toLowerCase()) {     case ‘avg’:     cell[columnName] = Number(cell[columnName]);     break;   }}my_dg.addEventListener(“cellEdit”, myListener);// ———-HTHpeter

  18. alfred says:

    Thanks Peter. Working fine now. Big THANKS!!!I can’t believe how hard it is to make numbers sort correctly….spent days figuring out and searching for answers. This tutorial is very possibly the ONLY number sorting tutorial on the INTERNET that actually works!Peter, is it possible for u to send me a e-mail?I’m actually trying to make a simple scoreboard that sorts score from highest to lowest… still have a bit more to do…. my first attempt at DataGrids/Arrays.If you can help, I’ll explain what I need. Should be very easy for you.ThanksAlf

  19. alfred says:

    Some things I can’t figure out:1) How can I make a button sort the avg cloume (always descening?) Instead of using the “headerRelease”.2) How to get a list of all the datagrid entries?eg. trace(my_array.join()); shows me [object Object],[object Object],….Thanks

  20. Mike says:

    Thanks!Was having headaches trying to cast my to numbers and sorting by this did the trick.. thanks for sharing!

  21. necoqij says:

    What do I need to do to create a primary and secondary sort key? e.g. first sort on Country then within that sort on Age

  22. aneeshanand says:

    all your codes sort the arrays, alryt. do it in this way – each column taking data from different arrays (or an XML) and the numeric columns need to be sorted. if i put your code, i will get the arrays sorted, but the datagrid is not updated. by tracing we can c the arrays are sorted numerically. its not reflected in the datagrid. is there any function to update datagrid to be called? plz do help..thank you.