Check out our Angular Book Series.

Why won't my AdvancedDataGrid sort correctly?

I was having some problems with sorting the Flex AdvancedDataGrid, and went into details of them in DotComIt's newsletter. I thought I'd share them here.

The Problem

I was creating a AdvancedDataGrid in a client project. The dataProvider for the grid had nested objects whose properties were being displayed in the column with an itemRenderer. I was also using a custom itemRenderer that would introspect the objects based on the dataField of the object. The combination of these things made two different columns always perform the same sort, even though my code told them to use a different sortCompareFunction.

This will make more sense with a sample. Let's start with the dataProvider:


[Bindable]
public var collection :ArrayCollection = new ArrayCollection([
{dummyValue:'',user:{firstName:'Arvid', lastName:'Zimmer'}},
{dummyValue:'',user:{firstName:'Jeffry', lastName:'Houser'}},
{dummyValue:'',user:{firstName:'Tom', lastName:'Amilton'}},
{dummyValue:'',user:{firstName:'Kyle', lastName:'Wellington'}},
{dummyValue:'',user:{firstName:'Zipper', lastName:'Stretch'}},
]);

Each property in the ArrayCollection has two values: a dummyValue which is a placeholder and a user value which is an object. I want the DataGrid to display the firstName and lastName in columns. This will do it:


<mx:AdvancedDataGrid dataProvider="{this.collection}"
sortExpertMode="true">

<mx:columns>
<mx:AdvancedDataGridColumn visible="false" />
<mx:AdvancedDataGridColumn headerText="first Name" sortable="true" dataField="user" sortCompareFunction="sortFirstName">
<mx:itemRenderer>
<fx:Component>
<s:MXAdvancedDataGridItemRenderer dataChange="itemrenderer1_dataChangeHandler(event)">
<fx:Script>
<![CDATA[
import mx.events.FlexEvent;
protected function itemrenderer1_dataChangeHandler(event:FlexEvent):void
{
if(!data){
return;
}
labelDisplay.text = data[this.advancedDataGridListData.dataField].firstName;
}
]]>

</fx:Script>
<s:Label id="labelDisplay" />
</s:MXAdvancedDataGridItemRenderer>
</fx:Component>
</mx:itemRenderer>
</mx:AdvancedDataGridColumn>
<mx:AdvancedDataGridColumn headerText="last Name" sortable="true" dataField="user" sortCompareFunction="sortLastName">
<mx:itemRenderer>
<fx:Component>
<s:MXAdvancedDataGridItemRenderer dataChange="itemrenderer1_dataChangeHandler(event)">
<fx:Script>
<![CDATA[
import mx.events.FlexEvent;
protected function itemrenderer1_dataChangeHandler(event:FlexEvent):void
{
if(!data){
return;
}
labelDisplay.text = data[this.advancedDataGridListData.dataField].lastName;
}
]]>

</fx:Script>
<s:Label id="labelDisplay" />
</s:MXAdvancedDataGridItemRenderer>
</fx:Component>
</mx:itemRenderer>
</mx:AdvancedDataGridColumn>
</mx:columns>
</mx:AdvancedDataGrid>

I simplified things from my client app, however the key to remember is that I was setting the dataField property so that the itemRenderer could access it. The problem with this is that clicking the column to sort would treat the columns as if they were identical. You can try a full sample. The top grid in the sample exhibits the problem.

Once one column was clicked, the other would always call the first column's sortCompareFunction; thus sorting based on the wrong criteria. For example. Load the app, click the first name column:

You'll see that the first name column is sorted. However, you can also see the sort arrow show up on the second column. Now click the last name column:

After clicking the last name column, the first name column is sorted in reverse order, but there is no sorting on the last name column. Reload the app, and try to sort the second column first. It sorts correctly. Then click the first column, and you'll see that only the second column is affected. Using the Flex Debugger I determined that once one column was clicked that column's sortCompareFunction was called for all columns that had the same dataField specified. That was not expected behavior.

My Solution

After some experimentation, I determined that the problem was that the dataField on both columns was identical. My solution was to add the dummy property into the dataProvider's objects and change one of the column's dataFields to point to the dummValue:


<mx:AdvancedDataGridColumn headerText="last Name" sortable="true" dataField="dummyValue" sortCompareFunction="sortLastName">

The side effect of this change is that I could no longer use the 'generic' itemRenderer. Instead of using the listData object in the renderer, I had to hard code the value. Like this:


labelDisplay.text = data.user.lastName;

I determined using a non-generic itemRenderer was better than having the columns not sort properly. I'm sure my client would agree. Click the first column in the grid and see this:

The first name column is sorted properly, and the last name column is untouched. Now click the last name column:

You see that the last name column is sorted properly and the first name column is untouched. This is how it is supposed to work.

Play with the full app here and check out the source code. The top grid shows the problem and the bottom grid shows the solution.

Sign up for DotComIt's Monthly Technical Newsletter

Comments (Comment Moderation is enabled. Your comment will not appear until approved.)
All Content Copyright 2005, 2006, 2007, 2008, 2009 Jeffry Houser. May not be reused without permission
BlogCFC was created by Raymond Camden. This blog is running version 5.9.2.002.