Thursday, June 07, 2007

Sorting Dates in a Flex Datagrid

So, file this under "I can't believe it took me that long to figure this out" catagory, but I just spent the past 2 hours trying to work through a solution for sorting a date column in a datagrid. By default, the datagrid sorting sorts by alphabetic or numeric order. If a date is in your dataprovider, it probably rendered it in the grid as a string. So, if you have a list of dates, the first ones showing up are probably every date with a Friday as a day. If you resort, all the Wednesdays are on top... GRRRR!

I did some searching and found some pointers on what to do. Most of them pointed to resorting the array (not an array collection) or ordering them on the server prior to getting them in Flex/Flash. The solution is much easier than working through a bunch of code for either of these. In your datagrid, define the columns with <mx:DataGridColumn> tags. In the date column define a 'sortCompareFunction' property to be a function like this:


private function compareDates(d1:Object, d2:Object):int
{

var d1ms:Number = new Date(d1.DATE FIELD NAME).getTime();
var d2ms:Number = new Date(d2.DATE FIELD NAME).getTime();

if(d1ms > d2ms)
{
return -1;
}
else if(d1ms < d2ms)
{
return 1;
}
else
{
return 0;
}
}



Replace your date field name from the dataprovider where indicated. That's it. Two hours for that... Boy, do I miss just working in Photoshop ;)

12 comments:

Anonymous said...

You just saved me a ton of time, thanks.

Anonymous said...

Works beautifully! Thanks!

Jacob said...

Hi,

I added the function like this
private function compareDates(d1:Object, d2:Object):int
{

var d1ms:Number = new Date(d1.LocalTestDate).getTime();
var d2ms:Number = new Date(d2.LocalTestDate).getTime();

if(d1ms > d2ms)
{
return -1;
}
else if(d1ms < d2ms)
{
return 1;
}
else
{
return 0;
}
}

where LocalTestDate is the dataField.

In the :DataGridColumn I defined as sortCompareFunction="compareDates".

However when I click the sort button in my datagrid, it doesn't sort the rows. What could be the problem?

Appreciate your co-operation.

Thanks

Jacob

Erik Loehfelm said...

Hi Jacob. I'm pretty sure that you can't pass an object into the compare function that has a parameter 'buried' in it like your trying to do. Have you tried it without the "d1.LocalTestDate" and just "d1"? The datagrid is smart enough to display the date elements in the correct column based on your DataGridColumn definitions (myColumn.dataField = someObject.LocalTestDate). It should be able to pull the correct 'object' - the data element that is in the particular column being sorted upon - and run the function.

Drop me a line if that is not the case.

- e

Jacob said...

I tried without d1.LocalTestDate just d1).getTime(), however still sort doesn't work.


private function compareDates(d1:Object, d2:Object):int
{

var d1ms:Number = new Date(d1).getTime();
var d2ms:Number = new Date(d2).getTime();


if(d1ms > d2ms)
{
return -1;
}
else if(d1ms < d2ms)
{
return 1;
}
else
{
return 0;
}
}

Erik Loehfelm said...

Hi Jacob. Sorry to hear you're still having issues.

I would suggest tracing or putting a breakpoint into the function to see what the values are that are being passed in. Try doing trace("object1="+d1) and be sure that the appropriate Date object (or string) is being passed in. If the date object (string) is not formatted in a way that is acceptable to easily create a true 'Date' object that the getTime() function will work on.

If the string is formatted like "June/2001/1" or some other bizarre style, the string-to-date conversion will not work on the Date() object instantiation. Check the references for the Date Object in the Flex/Flash help files to see that you are formatting the string properly for conversion.

Hope that helps.

- e

Jacob said...

Hi Erik,

My date format is for example is in this format
12-Feb-2008 14:08

Does this cause any problem?

is there any other is causing the problem?

Thanks

Jacob

Erik Loehfelm said...

Hi Jacob.

It looks like the date formatting of the string might be your issue. Here's the date page in the docs:

http://livedocs.adobe.com/flex/3/langref/Date.html#Date()

If you look at the second set of bullet points, it shows what the valid string formats are for 'automatic' transformation of the string to a date. You can also do some string manipulation to push the appropriate values into the date constructor if you'd like.

I think your easiest solution will be to rework your data so that it matches one of these string formats.

- e

Anonymous said...

Hi Erik,

I resolved the issue. Like you mentioned, I converted my string date to date format and then used your function to compare dates.

Thanks a lot.

Jacob

Jacob said...

Hi Erik,

I have another question regarding sorting.

When I click on the toggle to sort, the direction of
sorting is upside down, eg: for descending, it shows the up arrow and for
ascending it shows down arrow.

How can I resolve this issue?

Erik Loehfelm said...

Hi again!

For that, you'll need to use a Sort object:

http://livedocs.adobe.com/flex/3/langref/mx/collections/Sort.html

You'll create a simple Sort object that defines the function you're looking for (date 1 is earlier than date 2) and then apply that function to the ArrayCollection for your DataGrid by setting the sort property.

Don't forget to call the refresh() method after you apply the sort!

Kaushal Shah said...

This has saved me so much time. Thank you