Sunday, September 14, 2008

Sorting Flex DataGrid dynamically populated with XML

Well, recently i was doing some research on sorting in datagrid. I would like to share my problem and the way i solved it so that it will be useful to the other folks


Ingridients:

1 Datagrid

1 XML File which contains string data, numeric data and dates of different formats. Especially dates of format YYYY-MM-DD, MMM-YYYY

Structure:
<StringItem>value</StringItem>
<NumericItem>value</NumericItem>
<DateItemType1></DateItemType1>
<DateItemType2></DateItemType2>
<DateItemType3></DateItemType3>

Sample :
<TestDG>
<String1>abc</String1>
<String2>123</String2>
<Number1>1</Number1>
<Number2>37.5</Number2>
<Date1>2008-09-12</Date1>
<Date2>12-Sep-2008</Date2>
<Date3>Aug-2008</Date3>
</TestDG>

Problem:

I populate the datagrid data dynamically parsing the xml content. Now the problem is that, i need to sort each column based upon the type. If a specific column is numeric, i need to sort it numerically and same applies for date and string too.

Solution:

1. Inorder to manually sort data, u have an option in <mx:DataGridColumn> called sortCompareFunction, which is quite similar to compareTo in java. The function prototype looks this way

private function sortFunction(itemA:Object, itemB:Object):int {}

When u click the specicfic column header, this function will be called, the flex sorting algorithm passes two row values of that column at once and performs sort based on the value returned by sortFunction.

2. So here the next problem is, everytime two values are passed to sortFuction, the whole xml which is the dataprovider for the datagrid is passed to sortFunction. i.e. Both itemA, itemB has two copies of the whole dataprovider xml. If this is the case i can't perform sort which is specific to the column.

3. So to solve this, there an datagrid event called headerRelease. When ever a column header is clicked, this event is called. 
The function prototype looks this way
<mx:DataGrid id="datatable" dataProvider="{test}" headerRelease="storeColumn(event)">
private function storeColumn(event:DataGridEvent):void{
var dg:DataGrid = event.currentTarget as DataGrid;
column = String(event.dataField);
}


4. So i have obtained the columnname of the column to be sorted through this event and stored in a global variable.


5. Then in sortFunction, i made a look up of the specific column name, and based on its name i have determined the type and moved on sorting the values based on type.

private function sortFunction(itemA:Object, itemB:Object):int {
//Get the column name
// CASE1: If its of numeric type, do numeric compare
// CASE2: If its of date type, find its type and do date compare
// CASE3: If its of String type, do string compare.
}

6. The CASE3 in the above pseudocode itself is another problem. Determining datetypes and comparing the dates.

7. In the exploration of Flex Date parsing, the i have realized to things.

i) ITS NOT EASY
ii) FLEX DATESTRING PARSING DOESN'T SUPPORT DATE FORMATS WITH HYPHEN (-).

8. There are more than one ways to parse a string in flex.
i) Use Date.parse(dateString) which returns time in millis which can be used to construct date object. new Date(Date.parse(dateString)). But it supports only few formats. The formats use easily get in one google shot.
ii) Use SimpleDateFormatter which is not at all simple.
iii) Use DateField.parseStringToDate.
  All the above three doesn't support dates with hyphen (-) and unfortunately the formats i'm dealing with has only dates with hyphen(-). I have parsed it manually with split and then 
Filled date attributes in the following way

var date:Date = new Date();
date.month = parsed value; // For Month
date.fullYear = parsed value; // For year
date.date = parsed value // For date.

9. Once the date objects are obtained, i have compared both the objects using
ObjectUtil.dateCompare(date1,date2) which behaves in the same lines of string compare in java.
Similarly numeric comparision with ObjectUtil.numericCompare(value1,value2).


10. Finally  the sorting is done based upon respective types, and the mission accomplished.



EXPERTS: If you have better solution please share. 
NEWBIES: If your are running out of time, i hope this will help you in solving your problem. 

No comments: