DataGrid, labelFunction and namespaces
In a previous post I talked about my preferred method in Flex 2 for dealing with XML data that contains namespaces. Another task that gets complicated by the presence of 'namespaced XML' is populating a DataGrid with that data. Despite the usefulness of the use namespace directive, I have been unable to populate a DataGrid just by using the dataField attribute, as can be done when your data does not contain namespaces.
-
<mx:DataGrid x="10" y="291">
-
<mx:columns>
-
<mx:DataGridColumn headerText="Column 1" dataField="col1"/>
-
<mx:DataGridColumn headerText="Column 2" dataField="col2"/>
-
</mx:columns>
-
</mx:DataGrid>
The method I employ uses the labelFunction attribute of DataGridColumn, something that is most commonly used to let you specify a function to handle the formatting of data you would like displayed in that column. This approach allows you to use a single function for both special formatting of data and to gain access to data that resides in a namespace. Here is the basic format of my labelFunction:
-
private function genericLabelFunction(obj_data:Object, obj_dataGridColumn:DataGridColumn):String
-
{
-
use namespace DOCUMENT_METADATA_NAMESPACE;
-
var q:QName = new QName(DOCUMENT_METADATA_NAMESPACE, obj_dataGridColumn.dataField);
-
var str_data:String = obj_data[q];
-
-
switch(obj_dataGridColumn.dataField)
-
{
-
case "Status":
-
return (str_data == "InProgress") ? "In Progress" : str_data;
-
break;
-
case "PlanDataDate":
-
return str_data.substr(0, str_data.indexOf(" "))
-
break;
-
default:
-
return str_data;
-
break;
-
}
-
}
Another item that has proven useful for dealing with namespaced XML is the QName class. Short for 'qualified name', the QName constructor allows you to specify a namespace and a local name, which it uses to address the data you are targeting. Once we establish our QName object, we use it to reference the desired property of the data object (obj_data) that is passed into our labelFunction. Also notice that the local name is determined by the dataField attribute of the DataGridColumn object that was passed into the function. We now have a variable (str_data) that should contain the data from the node in our XML that has the same name as specified by our dataField attribute.
As shown in the first two cases, you can do further formatting to this data if desired. The default case takes care of all non-special cases, for when you would like to display the data as it exists in the XML and were simply using the labelFunction to get around namespace issues. Finally, here is a simple example of a DataGrid that uses our genericLabelFunction.
-
<mx:DataGrid dataProvider="{ModelLocator.getInstance().clientPlanList}" id="planList_dg">
-
<mx:columns>
-
<mx:DataGridColumn headerText="Industry" dataField="Industry" labelFunction="genericLabelFunction"/>
-
<mx:DataGridColumn headerText="Plan Date" dataField="PlanDataDate" labelFunction="genericLabelFunction"/>
-
<mx:DataGridColumn headerText="Status" dataField="Status" labelFunction="genericLabelFunction"/>
-
<mx:DataGridColumn headerText="Group Size" dataField="PlanSizeGroup" labelFunction="genericLabelFunction"/>
-
</mx:columns>
-
</mx:DataGrid>



on January 26th, 2007 at 4:30 am
Man, I cannot /tell/ you how great it is to be able to find a solution at 12:30 AM for a problem that would figure rather prominently in what you're showing to the executive team at 12:30 PM. Thanks a lot Ben, your contribution is greatly appreciated.
on January 29th, 2007 at 5:35 pm
This is beautiful!! I have been looking for this for over a day and now will be able to display data from .Net (with namespaces) within my datagrid.
One question, though. When I attempt to modify data, Flex ignores the namespace thus creating a new node entry within the bound XML. The new entry has the same tag name as what I want updated without a namespace.
If I manually update my XML, I will have the correct value in the "namespaced" node _and_ in the "non-namespaced" node.
Any thoughts?
on January 29th, 2007 at 8:33 pm
Hi Bruce, I'm glad this helped. I can't say I have any ideas on what might be happening with your xml though. In most cases these days I have actually opted to leave resultFormat alone (defaults to object) so that Flex will create objects for me. I tend to only use e4x if I need to access a limited number of deeply nested properties since the .. operator makes it so easy. You can use the ObjectTranslator class from darronschall.com to convert the generic objects Flex will create into class instances.
HTH,
Ben
on April 12th, 2007 at 1:56 am
hi nice site.
on May 9th, 2007 at 6:51 pm
Thanks a lot from Hungary (too)!
It was very usefull for me in my thesis!
The site is very good (with easy English, and useful examples)!
Szoke.
on July 18th, 2007 at 11:18 am
Would this mess up sorting? I added the function to my project in order for it to work, but now clicking on a column name does not sort properly. Good article, though. It helped me immensely.
on July 18th, 2007 at 6:29 pm
Hi Nolan, glad it helped. What exactly is the problem you're seeing? You may need a custom sort function.
on July 19th, 2007 at 1:25 pm
Yep... I didn't realize at first that I would need a custom sort function if I used a label function. I got it working though. Thanks!
on July 26th, 2007 at 6:55 pm
Thanks, I searched a LONG time for this. You helped a lot. I will post my labelFunction, pretty basic, but works for what I needed, which was simply to remove the freakin' namespace:
private function genericLabelFunction(dgcXML:Object,dcg:DataGridColumn):String
{
var currentItem:XML = XML(dgcXML);
var ns:Namespace = currentItem.namespace();
var displayValue:String = currentItem.ns::[dcg.dataField];
return displayValue;
}
on August 18th, 2007 at 8:25 am
Actually i am using httpservice and datagrid and i am generating xml from j2ee server that the httpservice will look on and i want some thing like this the xml should contain value and want attibute to be my column name in datagrid could u suggest me some thing
on June 23rd, 2008 at 6:38 pm
Hi,
Thanks for the post! Do you have the source file for this example somewhere?
Thanks!
on August 27th, 2008 at 10:24 am
Ben kicks ass!
on September 3rd, 2008 at 2:29 pm
another (possible) option here is to just remove the namespace from the XML.
the following code will not work out of context, but this is what i did to get my dataGrid/dataField to work right:
var xStr:String = incomingXML.toXMLString();
var rg:RegExp = /<v3:/g; // my namespace was 'v3'
xStr = xStr.replace(rg,"<"); take out the v3 but leave the open bracket
rg = new RegExp("</v3:", "g"); // dont forget the closing tags
xStr = xStr.replace(rg,"</"); // again, you have to leave the bracket and close
incomingXML = XML(xStr); // make back your XML object.
this assumes that you dont need the namespace anywhere else in your code; i did not. and this worked like a charm with no hacks.