Hierarchical and grouped data display

The AdvancedDataGrid control supports the display of hierarchical and grouped data. To support this display, the AdvancedDataGrid control displays a navigation tree in a column that lets you navigate the data hierarchy.

Hierarchical data is data already in a structure of parent and child data items. You can pass hierarchical data directly to the AdvancedDataGrid control. Grouped data is data that starts out as flat data with no inherent hierarchy. Before passing the flat data to the AdvancedDataGrid control, you specify one or more data fields that are used to group the flat data into a hierarchy.

The following code shows hierarchical data in the SimpleHierarchicalData.as file:

[Bindable]
private var dpHierarchy:ArrayCollection = new ArrayCollection([
  {Region:"Southwest", children: [
     {Region:"Arizona", children: [ 
        {Territory_Rep:"Barbara Jennings", Actual:38865, Estimate:40000}, 
        {Territory_Rep:"Dana Binn", Actual:29885, Estimate:30000}]},  
     {Region:"Central California", children: [ 
        {Territory_Rep:"Joe Smith", Actual:29134, Estimate:30000}]},  
     {Region:"Nevada", children: [ 
        {Territory_Rep:"Bethany Pittman", Actual:52888, Estimate:45000}]},  
     {Region:"Northern California", children: [ 
        {Territory_Rep:"Lauren Ipsum", Actual:38805, Estimate:40000}, 
        {Territory_Rep:"T.R. Smith", Actual:55498, Estimate:40000}]},  
     {Region:"Southern California", children: [ 
        {Territory_Rep:"Alice Treu", Actual:44985, Estimate:45000}, 
        {Territory_Rep:"Jane Grove", Actual:44913, Estimate:45000}]}
  ]}
]);

Notice that the data contains a top-level object that contains a Region field and multiple second-level children. Each second-level child also contains a Region field and one or more additional children. The following example shows the AdvancedDataGrid control displaying this data:

Each second-level child also contains a Region field and one or more additional children

The code for this example is in the section Controlling the navigation tree of the AdvancedDataGrid control.

To display flat data as a hierarchy, you group the rows of the flat data before passing the data to the AdvancedDataGrid control. The following code contains a variation on the hierarchical data shown in the previous image, but arranges the data in a flat data structure:

[Bindable]
private var dpFlat:ArrayCollection = new ArrayCollection([
  {Region:"Southwest", Territory:"Arizona", 
      Territory_Rep:"Barbara Jennings", Actual:38865, Estimate:40000}, 
  {Region:"Southwest", Territory:"Arizona", 
      Territory_Rep:"Dana Binn", Actual:29885, Estimate:30000},  
  {Region:"Southwest", Territory:"Central California", 
      Territory_Rep:"Joe Smith", Actual:29134, Estimate:30000},  
  {Region:"Southwest", Territory:"Nevada", 
      Territory_Rep:"Bethany Pittman", Actual:52888, Estimate:45000},  
  {Region:"Southwest", Territory:"Northern California", 
      Territory_Rep:"Lauren Ipsum", Actual:38805, Estimate:40000}, 
  {Region:"Southwest", Territory:"Northern California", 
      Territory_Rep:"T.R. Smith", Actual:55498, Estimate:40000},  
  {Region:"Southwest", Territory:"Southern California", 
      Territory_Rep:"Alice Treu", Actual:44985, Estimate:45000}, 
  {Region:"Southwest", Territory:"Southern California", 
      Territory_Rep:"Jane Grove", Actual:44913, Estimate:45000}
]);

In this example, the data contains a single level of individual records with no inherent hierarchy. To group the data, you specify one or more data fields used to arrange the data in a hierarchy. The following example shows the AdvancedDataGrid control where the flat data has been grouped by the Region field of the data:

The code for this example is in the section Displaying grouped data.

Setting the data provider with hierarchical data

To configure the AdvancedDataGrid control to display hierarchical data and the navigation tree, you pass to the dataProvider property an instance of the HierarchicalData class or of the GroupingCollection2 class. Use the HierarchicalData class when your data is already arranged in a hierarchy. Use the GroupingCollection2 class when your data is in a flat structure. As part of configuring an instance of the GroupingCollection2 class, you specify one or more data fields that are used to arrange the flat data in a hierarchy.

When using the AdvancedDataGrid control with hierarchical data, you might have to free memory when you replace the data provider of the control. For more information, see the article Free memory when you replace the data provider of the AdvancedDataGrid control.

For more information on displaying hierarchical data, see Displaying hierarchical data. For more information on displaying grouped data, see Displaying grouped data.

You can create an instance of the HierarchicalData class or an instance of the GroupingCollection2 class from any data that you can use as a data provider. However, the AdvancedDataGrid control modifies its internal representation of the data as follows:

  • An Array is represented internally by the AdvancedDataGrid control as an instance of the ArrayCollection class.

  • An ArrayCollection class is represented internally by the AdvancedDataGrid control as an instance of the ArrayCollection class.

  • A String that contains valid XML text is represented internally by the AdvancedDataGrid control as an instance of the XMLListCollection class.

  • An XMLNode class or an XMLListclass is represented internally by the AdvancedDataGrid control as an instance of the XMLListCollection class.

  • Any object that implements the ICollectionView interface is represented internally by the AdvancedDataGrid control as an instance of the ICollectionView interface.

  • An object of any other data type is wrapped in an Array instance with the object as its sole entry.

For example, you use an Array to create an instance of the HierarchicalData class, and then pass that HierarchicalData instance to the AdvancedDataGrid.dataProvider property. If you read the data back from the AdvancedDataGrid.dataProvider property, it is returned as an ArrayCollection instance.

Calling validateNow() after setting the data provider

In some situations, you may set the data provider of the AdvancedDataGrid control to hierarchical or grouped data, and then immediately try to perform an action based on the new data provider. This typically occurs when you set the dataProvider property in ActionScript, as the following example shows:

adg.dataProvider = groupedCollection; 
adg.expandAll();

In this example, the call to expandAll() fails because the AdvancedDataGrid control is in the process of setting the dataProvider property, and the expandAll() method either processes the old value of the dataProvider property, if one existed, or does nothing.

In this situation, you must insert the validateNow() method after setting the data provider. The validateNow() method validates and updates the properties and layout of the control, and then redraws it, if necessary. The following example inserts the validateNow() method before the expandAll() method:

adg.dataProvider = groupedCollection; 
adg.validateNow(); 
adg.expandAll();

Do not insert the validateNow() method every time you set the dataProvider property because it can affect the performance of your application; it is only required in some situations when you attempt to perform an operation on the control immediately after setting the dataProvider property.

Controlling the navigation tree of the AdvancedDataGrid control

The AdvancedDataGrid control is sometimes referred to as a tree datagrid because a column of the control uses an expandable tree to determine which rows are currently visible in the control. Often, the tree appears in the left-most column of the control, where the first column of the control is associated with a field of the control’s data provider. That data field of the data provider provides the text for the labels of the tree nodes.

In the following example, you populate the AdvancedDataGrid control with the hierarchal data structure shown in Hierarchical and grouped data display. The data contains a top-level object that contains a Region field, and multiple second-level children. Each second-level child also contains a Region field and one or more children.

The AdvancedDataGrid control in this example defines four columns to display the data: Region, Territory Rep, Actual, and Estimate.

<?xml version="1.0"?>
<!-- dpcontrols/adg/SimpleHierarchicalADG.mxml -->
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
    xmlns:mx="library://ns.adobe.com/flex/mx" 
    xmlns:s="library://ns.adobe.com/flex/spark">

  <fx:Script>
    <![CDATA[
          import mx.collections.ArrayCollection;
                    
          include "SimpleHierarchicalData.as";
      ]]>
    </fx:Script>

    <mx:AdvancedDataGrid width="100%" height="100%">
        <mx:dataProvider>
            <mx:HierarchicalData source="{dpHierarchy}"/>
        </mx:dataProvider>
        <mx:columns>
            <mx:AdvancedDataGridColumn dataField="Region"/>
            <mx:AdvancedDataGridColumn dataField="Territory_Rep"
                headerText="Territory Rep"/>
            <mx:AdvancedDataGridColumn dataField="Actual"/>
            <mx:AdvancedDataGridColumn dataField="Estimate"/>
        </mx:columns>
    </mx:AdvancedDataGrid>    
</s:Application>

The executing SWF file for the previous example is shown below:

The following image shows the AdvancedDataGrid control created by this example. The control displays a folder icon to represent branch nodes of the tree, and a file icon to represent leaf nodes. The first column of the control is associated with the Region field of the data provider, so the tree labels display the value of the Region field.

AdvancedDataGrid control where the flat data has been grouped by the Region field of the data:

Notice that the leaf icon for the tree does not show a label. This is because the individual records for each territory representative do not contain a Region field.

While the tree is often positioned in the left-most column of the control, you can use the treeColumn property to specify any column in the control, as the following example shows:

<?xml version="1.0"?>
<!-- dpcontrols/adg/HierarchicalADGCategoriesTreeColumn.mxml -->
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
    xmlns:mx="library://ns.adobe.com/flex/mx" 
    xmlns:s="library://ns.adobe.com/flex/spark">

  <fx:Script>
    <![CDATA[
          import mx.collections.ArrayCollection;
                
          include "HierarchicalDataCategories.as";
      ]]>
    </fx:Script>

    <mx:AdvancedDataGrid 
        width="100%" height="100%"
        treeColumn="{rep}"> 
        <mx:dataProvider>
            <mx:HierarchicalData source="{dpHierarchy}" 
                childrenField="categories"/>
        </mx:dataProvider>
        <mx:columns>
            <mx:AdvancedDataGridColumn dataField="Region"/>
            <mx:AdvancedDataGridColumn id="rep" 
                dataField="Territory_Rep"
                headerText="Territory Rep"/>
            <mx:AdvancedDataGridColumn dataField="Actual"/>
            <mx:AdvancedDataGridColumn dataField="Estimate"/>
        </mx:columns>
    </mx:AdvancedDataGrid>    
</s:Application>

The executing SWF file for the previous example is shown below:

Setting navigation tree icons and labels

The navigation tree lets you control the icons and labels used for the branch and leaf nodes. For example, you can display a tree of labels with no icons, a tree with just folder icons, a tree with no labels at all, or a tree in its own column that is not associated with any data field.

The following table describes the style properties of the AdvancedDataGrid control that you use to set the tree icons:

Style property

Description

defaultLeafIcon

Specifies the leaf icon.

disclosureClosedIcon

Specifies the icon that is displayed next to a closed branch node. The default icon is a black triangle.

disclosureOpenIcon

Specifies the icon that is displayed next to an open branch node. The default icon is a black triangle.

folderClosedIcon

Specifies the folder closed icon for a branch node.

folderOpenIcon

Specifies the folder open icon for a branch node.

The following example sets the default leaf icon to null to hide it, and uses custom icons for the folder open and closed icons:

<?xml version="1.0"?>
<!-- dpcontrols/adg/SimpleHierarchicalADGTreeIcons.mxml -->
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
    xmlns:mx="library://ns.adobe.com/flex/mx" 
    xmlns:s="library://ns.adobe.com/flex/spark">

  <fx:Script>
    <![CDATA[
          import mx.collections.ArrayCollection;
                
          include "SimpleHierarchicalData.as";
      ]]>
    </fx:Script>

    <mx:AdvancedDataGrid width="100%" height="100%" 
        defaultLeafIcon="{null}"
        folderOpenIcon="@Embed(source='assets/folderOpenIcon.jpg')"
        folderClosedIcon="@Embed(source='assets/folderClosedIcon.jpg')">
        <mx:dataProvider>
            <mx:HierarchicalData source="{dpHierarchy}"/>
        </mx:dataProvider>
        <mx:columns>
            <mx:AdvancedDataGridColumn dataField="Region"/>
            <mx:AdvancedDataGridColumn dataField="Territory_Rep"
                headerText="Territory Rep"/>
            <mx:AdvancedDataGridColumn dataField="Actual"/>
            <mx:AdvancedDataGridColumn dataField="Estimate"/>
        </mx:columns>
    </mx:AdvancedDataGrid>    
</s:Application>

The executing SWF file for the previous example is shown below:

You can also specify the styles by using the setStyle() method, and by using an <fx:Style> tag, as the following example shows:

<fx:Style> 
    @namespace s "library://ns.adobe.com/flex/spark"; 
    s|AdvancedDataGrid { 
        defaultLeafIcon:ClassReference(null); 
        folderOpenIcon:Embed(source='assets/folderOpenIcon.jpg'); 
        folderClosedIcon:Embed(source='assets/folderClosedIcon.jpg'); 
    } 
</fx:Style>

Using the groupIconFunction and groupLabelFunction properties

Use the groupIconFunction and groupLabelFunction properties of the AdvancedDataGrid class to define callback functions to control the display of the leaf nodes of the navigation tree. The callback function specified by the groupIconFunction property controls the icon, and the callback function specified by the groupLabelFunction controls the label.

The following example uses the groupIconFunction property to display a custom icon for the top level node of the navigation tree, and display the default icon for all other leaf nodes of the tree:

<?xml version="1.0"?>
<!-- dpcontrols/adg/SimpleHierarchicalADGGroupIcon.mxml -->
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
    xmlns:mx="library://ns.adobe.com/flex/mx" 
    xmlns:s="library://ns.adobe.com/flex/spark">

  <fx:Script>
    <![CDATA[
          import mx.collections.ArrayCollection;
                    
          include "SimpleHierarchicalData.as";

         // Embed the icon for the groups.
         [Bindable]
         [Embed(source="assets/topTreeIcon.png")] 
         public var icn:Class;
        
         // Define the groupIconFunction callback function.
         public function myIconFunc(item:Object, depth:int):Class {
             if(depth == 1)
                 // If this is the top-level of the tree, return the icon.
                 return icn;
             else
                 // If this is any other level, return null.
                 return null;
         }
      ]]>
    </fx:Script>

    <mx:AdvancedDataGrid 
        width="100%" height="100%"
        groupIconFunction="myIconFunc">
        <mx:dataProvider>
            <mx:HierarchicalData source="{dpHierarchy}"/>
        </mx:dataProvider>
        <mx:columns>
            <mx:AdvancedDataGridColumn dataField="Region"/>
            <mx:AdvancedDataGridColumn dataField="Territory_Rep"
                headerText="Territory Rep"/>
            <mx:AdvancedDataGridColumn dataField="Actual"/>
            <mx:AdvancedDataGridColumn dataField="Estimate"/>
        </mx:columns>
    </mx:AdvancedDataGrid>    
</s:Application>

The executing SWF file for the previous example is shown below:

Creating a separate column for the navigation tree

In the examples in Hierarchical and grouped data display, the first column also displays the Region field of the data. Therefore, as you expand the nodes of the navigation tree, the label of each tree node corresponds to the value of the Region field in the data provider for that row. For the leaf nodes of the tree, the data provider does not contain a value for the Region field, so the labels for the leaf nodes are blank.

You can also put the navigation tree in its own column, where the column is not associated with a data field, as the following example shows:

This example does not associate a data field with the column that contains the tree, so the tree icons appear with no label. This example also sets the folderClosedIcon, folderOpenIcon, and defaultLeafIcon properties of the AdvancedDataGrid control to null, but does display the disclosure icons so that the user can still open and close tree nodes.

The following code implements this example. Notice that the first column is not associated with a data field. Because it is the first column in the data grid, the AdvancedDataGrid control automatically uses it to display the navigation tree.

<?xml version="1.0"?>
<!-- dpcontrols/adg/SimpleHierarchicalADGTreeColumn.mxml -->
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
    xmlns:mx="library://ns.adobe.com/flex/mx" 
    xmlns:s="library://ns.adobe.com/flex/spark">

  <fx:Script>
    <![CDATA[
          import mx.collections.ArrayCollection;
                
          include "SimpleHierarchicalData.as";
      ]]>
    </fx:Script>

    <mx:AdvancedDataGrid width="100%" height="100%" 
        folderClosedIcon="{null}" 
        folderOpenIcon="{null}" 
        defaultLeafIcon="{null}">
        <mx:dataProvider>
            <mx:HierarchicalData source="{dpHierarchy}"/>
        </mx:dataProvider>
        <mx:columns>
            <mx:AdvancedDataGridColumn headerText="" width="50"/>
            <mx:AdvancedDataGridColumn dataField="Region"/>
            <mx:AdvancedDataGridColumn dataField="Territory_Rep"
                headerText="Territory Rep"/>
            <mx:AdvancedDataGridColumn dataField="Actual"/>
            <mx:AdvancedDataGridColumn dataField="Estimate"/>
        </mx:columns>
    </mx:AdvancedDataGrid>    
</s:Application>

The executing SWF file for the previous example is shown below: