Setting a DataGrid control’s data provider to an XML object in Flex

The following example shows how you can use an XML object as a data provider for a Flex DataGrid control and use a custom label function to display the XML node’s name.

Full code after the jump.

View MXML

<?xml version="1.0" encoding="utf-8"?>
<!-- http://blog.flexexamples.com/2008/11/05/setting-a-datagrid-controls-data-provider-to-an-xml-object-in-flex/ -->
<mx:Application name="DataGrid_dataProvider_XML_test2"
        xmlns:mx="http://www.adobe.com/2006/mxml"
        layout="vertical"
        verticalAlign="middle"
        backgroundColor="white">

    <mx:Script>
        <![CDATA[
            import mx.controls.dataGridClasses.DataGridColumn;
            import mx.utils.ObjectUtil;

            private function labelFunc(item:XML, col:DataGridColumn):String {
                return item.name();
            }

            private function nameSortCompareFunc(itemA:XML, itemB:XML):int {
                return ObjectUtil.stringCompare(dataGridCol1.itemToLabel(itemA), dataGridCol1.itemToLabel(itemB), true);
            }

            private function typeSortCompareFunc(itemA:XML, itemB:XML):int {
                return ObjectUtil.numericCompare(itemA.@type, itemB.@type);
            }
        ]]>
    </mx:Script>

    <mx:XML id="xmlDP" source="data/log.xml" />

    <mx:DataGrid id="dataGrid"
            dataProvider="{xmlDP.children()}"
            verticalScrollPolicy="on">
        <mx:columns>
            <mx:DataGridColumn id="dataGridCol1"
                    headerText="Name"
                    labelFunction="labelFunc"
                    sortCompareFunction="nameSortCompareFunc"
                    width="80"/>
            <mx:DataGridColumn id="dataGridCol2"
                    dataField="@type"
                    headerText="Type"
                    sortCompareFunction="typeSortCompareFunc"
                    width="50" />
            <mx:DataGridColumn id="dataGridCol3"
                    dataField="@message"
                    headerText="Message"
                    width="200" />
        </mx:columns>
    </mx:DataGrid>

</mx:Application>

data/log.xml

<?xml version="1.0" encoding="utf-8"?>
<!-- http://blog.flexexamples.com/2008/11/05/setting-a-datagrid-controls-data-provider-to-an-xml-object-in-flex/ -->
<log>
    <error type="13" message="Cannot do something or other." />
    <warning type="49" message="Whoa, that was close!" />
    <error type="134" message="Abort! Abort!" />
    <error type="99" message="Wait, do you smell smoke?" />
</log>

View source is enabled in the following example.

Due to popular demand, here is the “same” example in a more ActionScript friendly format:

View MXML

<?xml version="1.0" encoding="utf-8"?>
<!-- http://blog.flexexamples.com/2008/11/05/setting-a-datagrid-controls-data-provider-to-an-xml-object-in-flex/ -->
<mx:Application name="DataGrid_dataProvider_XML_test2"
        xmlns:mx="http://www.adobe.com/2006/mxml"
        layout="vertical"
        verticalAlign="middle"
        backgroundColor="white"
        initialize="init();">

    <mx:XML id="xmlDP" source="data/log.xml" />

    <mx:Script>
        <![CDATA[
            import mx.core.ScrollPolicy;
            import mx.controls.DataGrid;
            import mx.controls.dataGridClasses.DataGridColumn;
            import mx.utils.ObjectUtil;

            private var dataGrid:DataGrid;
            private var dataGridCol1:DataGridColumn;
            private var dataGridCol2:DataGridColumn;
            private var dataGridCol3:DataGridColumn;

            private function init():void {
                dataGridCol1 = new DataGridColumn();
                dataGridCol1.headerText = "Name";
                dataGridCol1.labelFunction = labelFunc;
                dataGridCol1.sortCompareFunction = nameSortCompareFunc;
                dataGridCol1.width = 80;

                dataGridCol2 = new DataGridColumn("@type");
                dataGridCol2.headerText = "Type";
                dataGridCol2.sortCompareFunction = typeSortCompareFunc;
                dataGridCol2.width = 50;

                dataGridCol3 = new DataGridColumn("@message");
                dataGridCol3.headerText = "Message";
                dataGridCol3.width = 200;

                dataGrid = new DataGrid();
                dataGrid.columns = [dataGridCol1, dataGridCol2, dataGridCol3];
                dataGrid.dataProvider = xmlDP.children();
                dataGrid.verticalScrollPolicy = ScrollPolicy.ON;
                addChild(dataGrid);
            }

            private function labelFunc(item:XML, col:DataGridColumn):String {
                return item.name();
            }

            private function nameSortCompareFunc(itemA:XML, itemB:XML):int {
                return ObjectUtil.stringCompare(dataGridCol1.itemToLabel(itemA), dataGridCol1.itemToLabel(itemB), true);
            }

            private function typeSortCompareFunc(itemA:XML, itemB:XML):int {
                return ObjectUtil.numericCompare(itemA.@type, itemB.@type);
            }
        ]]>
    </mx:Script>

</mx:Application>

6 thoughts on “Setting a DataGrid control’s data provider to an XML object in Flex

  1. Funny I just did almost the exact thing for work and realize that I have never been able to “just load” the XML without parsing the attributes via E4X and create the DataGridColumns. Wonder if there’s a way to tell the datagrid to just load the attributes as columns?

  2. Boaz,

    This seems to “work”, and displays two columns (@message and @type):

    <mx:DataGrid id="dataGrid"
            dataProvider="{xmlDP.children()}"
            verticalScrollPolicy="on" />
    

    I’m not sure how it’d handle the case where child nodes may have different attribute lists. Plus you couldn’t really set column headers, sort compare functions, label functions, etc. unless you explicitly defined the DataGridColumn objects explicitly.

    Peter

  3. After a datagrid is populated with data via an HTTP service, is there a way to send the data from a randomly selected row to several text box fields elsewhere on the form?

    Right now my application sends the data fine with an itemclick event, but I would to have the user see some good example data when the application loads.

  4. Kirk,

    Sure, just use databinding (bind the form fields to a field in the DataGrid control’s selectedItem object) and select a random index in the DataGrid by setting the selectedIndex property to a value between 0 and the data provider length – 1.

    Peter

  5. thanks for the suggestion on using children(). And yeah, it does kill the idea for having to set the column headers manually anyway.

Comments are closed.