Accessibility

Flex Quick Start: Building an advanced user interface

Table of contents


Using data providers

Several Adobe® Flex™ framework components, including all list-based controls, represent data from a data provider, an object that contains data required by the control. For example, a Tree control's data provider determines the structure of the tree and any associated data assigned to each tree node, and a ComboBox control's data provider determines the items in the control's drop-down list. Many standard controls, including the ColorPicker and MenuBar controls also get data from a data provider. Controls that display application data are sometimes referred to as data provider controls.

This Quick Start describes several ways of using data providers.

Using an array as a data provider

The simplest data provider is an Array of Strings or Objects. The following example uses an Array of Strings as a data provider to create a static ComboBox control.

Example

<?xml version="1.0" encoding="utf-8"?>
<mx:Application 
    xmlns:mx="http://www.adobe.com/2006/mxml"
    viewSourceURL="src/DataProviderArray/index.html"

    width="150" height="140"
>
    <mx:Script>
        <![CDATA[

            []
            public var myArray:Array = ["AL", "AK", "AR"]; 
        ]]>

    </mx:Script>
    <mx:ComboBox id="statesCombo" dataProvider="{myArray}"/> 
</mx:Application>

Result

AlertThis content requires Flash

Download the free Flash Player now!

Get Adobe Flash Player

To view the full source, right-click the Flex application and select View Source from the context menu.

Limitations of arrays and objects as data providers

Using a raw data object, such as an Array or Object, as a data provider has limitations:

Note: These limitations were new in Flex 2. In Flex 1.5 and earlier, Flex used to mix in event-dispatching logic as well as methods for accessing, sorting and filtering data into an Array object when it was set as a dataProvider. It is important to keep this in mind if you are migrating your Flex 1.5 applications to Flex 2 or Flex 3. These limitations are overcome by using the new Collections classes, as the following section explains.

In the following example, three bloggers' names are displayed in a List control that uses an Array as its data provider. When a user presses the Add A Blogger button, Flex adds a fourth blogger's name to the Array. However, the added name does not immediately show up in the List control unless you reassign the control's dataProvider property by pressing the Reassign Data Provider button.

Example

<?xml version="1.0" encoding="utf-8"?>

<mx:Application 
    xmlns:mx="http://www.adobe.com/2006/mxml"
    viewSourceURL="src/DataProviderArrayLimitations/index.html"
    width="350"    height="220"
>

    <mx:Script>
        <![CDATA[
            []
            public var bloggersArray:Array = 
                ["Andy Budd", "Grant Skinner", "Paul Booth"]; 
        ]]>

    </mx:Script>
    <mx:Panel title="Bloggers we love!" width="100%">
        <mx:List 
            id="bloggersList" width="100%" rowCount="4" 
            dataProvider="{bloggersArray}"

        />         
    </mx:Panel>
    <mx:ApplicationControlBar>
        <mx:Button 
            label="Add a blogger!" 
            click="bloggersArray[3]='Pete-Barr Watson';"

        />
        <mx:Button 
            label="Reassign data provider." 
            click="bloggersList.dataProvider=bloggersArray"
        />                
    </mx:ApplicationControlBar>

</mx:Application>

Result

AlertThis content requires Flash

Download the free Flash Player now!

Get Adobe Flash Player

To view the full source, right-click the Flex application and select View Source from the context menu.

Using collections as data providers in MXML

Flex provides a collection mechanism to ensure data synchronization and provide both simpler and more sophisticated data access and manipulation tools.

You can use an object that implements the ICollectionView or IList interface as a data provider directly in an MXML control by assigning it to the component's dataProvider property. You can do this either in MXML or by using ActionScript.

The following example shows you how to create an ArrayCollection and apply it as the data provider of a List control by using MXML.

<?xml version="1.0" encoding="utf-8"?>

<mx:Application 
    xmlns:mx="http://www.adobe.com/2006/mxml"
    viewSourceURL="src/DataProviderArrayLimitations/index.html"
    width="350"    height="220"
>

    <mx:Panel title="Bloggers we love!" width="100%">

        <mx:List id="bloggersList" width="100%" rowCount="4">

            <mx:dataProvider>
                <mx:ArrayCollection id="bloggers">
                    <mx:Object label="Andy Budd" url="http://andybudd.com"/>

                    <mx:Object label="Grant Skinner" url="http://gskinner.com"/>
                    <mx:Object label="Paul Booth" url="http://paulbooth.com"/>

                </mx:ArrayCollection>
            </mx:dataProvider>
        </mx:List>         

        <mx:ControlBar horizontalAlign="center">
            <mx:Button 
                label="Add a blogger!" 
                click="bloggers.addItem({label:'Pete-Barr Watson', url:'http://petebarrwatson.com/'});"

            />
        </mx:ControlBar>

    </mx:Panel>
</mx:Application>

AlertThis content requires Flash

Download the free Flash Player now!

Get Adobe Flash Player

To view the full source, right-click the Flex application and select View Source from the context menu.

Using collections as data providers (by using ActionScript)

The following example shows you how to create an ArrayCollection and apply it as the data provider of a List control by using ActionScript.

<?xml version="1.0" encoding="utf-8"?>
<mx:Application 
    xmlns:mx="http://www.adobe.com/2006/mxml"
    viewSourceURL="src/DataProviderArrayLimitations/index.html"

    width="350"    height="220"
    creationComplete="creationCompleteHandler(event);"
>
    <mx:Script>

        <![CDATA[
            import mx.collections.ArrayCollection;
            import mx.events.FlexEvent;
            
            private var bloggersArray:Array = 
            [

                {label: "Andy Budd", url:"http://andybudd.com"},
                {label: "Grant Skinner", url:"http://gskinner.com"},
                {label: "Paul Booth", url:"http://paulbooth.com"}

            ];
            
            []
            private var bloggersCol:ArrayCollection;
            
            private function creationCompleteHandler(event:FlexEvent):void

            {
                bloggersCol = new ArrayCollection (bloggersArray);    
            }
        ]]>

    </mx:Script>
    <mx:Panel title="Bloggers we love!" width="100%">

        <mx:List 
            id="bloggersList" width="100%" rowCount="4"

            dataProvider="{bloggersCol}" 
        />

        <mx:ControlBar horizontalAlign="center">
            <mx:Button 
                label="Add a blogger!" 
                click="bloggersCol.addItem({label:'Pete-Barr Watson', url:'http://petebarrwatson.com/'});"

            />
        </mx:ControlBar>

    </mx:Panel>
</mx:Application>

Result

AlertThis content requires Flash

Download the free Flash Player now!

Get Adobe Flash Player

To view the full source, right-click the Flex application and select View Source from the context menu.

Tip: If you know that a control's data provider can always be represented by a specific collection class you can use that class directly, as shown in the preceding example with the ArrayCollection class. However, if your control must be able to handle different types of collections — for example, either an ArrayCollection or an XMLListCollection — you should bind your data provider to a property of type ICollectionView as all collection classes implement the ICollectionView interface, as shown in the following snippet:

[]
private var bloggersCol:ICollectionView;

Using externally-loaded data as a data provider

Loading in and displaying external data is a very common feature in rich Internet applications. The HTTPService control in Flex is one mechanism for loading in external data. To display XML data read by an HTTPService control into a Flex data provider control, store the repeating set of nodes that contains your collection in an ArrayCollection and bind that to the dataProvider property of your control.

Tip: Ensure that you deploy the data file to the correct location. The URL that you specify for the HTTPService control is relative to the location of the HTML file that loads in your Flex application, not relative to the location of your Flex application's SWF file.

Also, always use a forward slash (/) when specifying the URL for the HTTPService control. Using a backslash works when you test your Flex application offline, but may not work on your server because it may be URL encoded to %5C.

You can also bind your data provider control to the lastResult property of your HTTPService instance directly; however, the slightly more verbose method shown in the following example makes the code easier to maintain and scale.

The following example uses an HTTPService control to read in an XML file and then uses the read-in data as the data provider for a List control.

Example

Model (bloggers.xml)

<bloggers>
    <blogger>
        <name>Andy Budd</name>
        <url>http://andybudd.com</url>
    </blogger>

    <blogger>
        <name>Grant Skinner</name>
        <url>http://gskinner.com</url>
    </blogger>
    <blogger>

        <name>Paul Booth</name>
        <url>http://paulbooth.com</url>
    </blogger>    
</bloggers>

Main application file

<?xml version="1.0" encoding="utf-8"?>
<mx:Application 
    xmlns:mx="http://www.adobe.com/2006/mxml"
    viewSourceURL="src/DataProviderExternal/index.html"

    width="350"    height="220"
    creationComplete="bs.send();"
>
    <mx:Script>

        <![CDATA[
            import mx.managers.CursorManager;
            import mx.rpc.events.InvokeEvent;
            import mx.controls.Alert;
            import mx.rpc.events.FaultEvent;
            import mx.rpc.events.ResultEvent;
            import mx.collections.ArrayCollection;
            
            []

            private var bloggersCol:ArrayCollection;
            
            // Gets called when HTTPService is invoked to
            // request the XML.
            private function bsInvokeHandler(event:InvokeEvent):void

            {
                // Display the busy cursor
                CursorManager.setBusyCursor();
            }
            
            // Gets called when the XML is successfully loaded.
            private function bsResultHandler(event:ResultEvent):void

            {
                // Save a reference to the list of bloggers
                bloggersCol = event.result.bloggers.blogger;
                
                // Hide the busy cursor
                CursorManager.removeBusyCursor();
            }

            
            private function bsFaultHandler(event:FaultEvent):void
            {

                // There was an error in loading the XML
                Alert.show (event.fault.message);    
                
                // Hide the busy cursor
                CursorManager.removeBusyCursor();
            }
        ]]>

    </mx:Script>
    
    <!-- Service to load in XML -->
    <mx:HTTPService
        id="bs" 
        url="data/bloggers.xml"

        invoke="bsInvokeHandler(event);"
        result="bsResultHandler(event);"
        fault="bsFaultHandler(event);"

    />
    
    <mx:Panel title="Bloggers we love!" width="100%">

        <mx:List 
            id="bloggersList" width="100%" rowCount="4"

            dataProvider="{bloggersCol}"
            labelField="name" 
        />

        <mx:ControlBar horizontalAlign="center">

            <mx:Button 
                label="Add a blogger!" 
                click="bloggersCol.addItem({name:'Pete-Barr Watson', url:'http://petebarrwatson.com/'});"

            />
        </mx:ControlBar>

    </mx:Panel>
</mx:Application>

Result

AlertThis content requires Flash

Download the free Flash Player now!

Get Adobe Flash Player

To view the full source, right-click the Flex application and select View Source from the context menu.

Modifying data in data providers and listening for events

Collection classes in Flex implement the IList interface which provides methods for modifying (adding, removing, updating) items in a collection. You can use the IList interface methods and properties directly on any of the following classes or properties: ArrayCollection class, XMLList class, and the dataProvider property of standard Flex controls. The most important methods in the IList interface are addItem(), removeItem(), and setItemAt() for adding, removing, and updating data items, respectively. There are also addItemAt() and removeItemAt() methods, which, like the setItemAt() method, take a second parameter that corresponds to the index in the collection that you want to affect. The length property exposed by the IList interface returns the number of items in a collection.

The Flex collection mechanism also includes events that represent changes to the collection. Classes that implement the IList or ICollectionView interface dispatch a CollectionEvent class event (mx.events.CollectionEvent) whenever the collection changes. All collection events have the type property value CollectionEvent.COLLECTION_CHANGE.

Note: You can also sort and filter the data in a collection by using the methods of the ICollectionView interface. For more information, see "Using ICollectionView interface methods and properties" in the Flex 3 Developer Guide.

The CollectionEvent object includes a kind property that indicates the way in which the collection changed; you can determine the change by comparing the kind property value with the CollectionEventKind constants. The main constants are ADD, REMOVE, and UPDATE.

The CollectionEvent object also includes an items property that is an Array of objects whose type varies depending on the kind of event that the object dispatched. For ADD and REMOVE events, the array contains the added or removed items. For UPDATE events, the items property contains an Array of PropertyChangeEvent event objects. These objects' properties indicate the type of changes and the propertys' values before and after the changes. For example, the kind property of the PropertyChangeEvent class indicates the way in which the property changed; you can determine the change type by comparing the kind property value with the PropertyChangeEventKind constants, UPDATE and DELETE.

The following example listens for the change event on a DataGrid control to create a master-detail relationship in which selecting a row on the DataGrid displays the data in that row in several form controls so you can edit the data. (An alternative to using a master-detail relationship is to make the DataGrid control editable.) The example lets you add, remove, or modify data in a DataGrid control using the addItem(), removeItem(), and setItemAt() methods of the IList interface. It also listens for the collectionChange event on the ArrayCollection to keep a log of data that is added, removed and updated.

Example

<?xml version="1.0" encoding="utf-8"?>
<mx:Application 
    xmlns:mx="http://www.adobe.com/2006/mxml" 
     viewSourceURL="src/DataProviderModifyingAndEvents/index.html"
    width="525" height="530" 

>
    <mx:Script>
        <![CDATA[
            
            import mx.events.*;
            import mx.collections.*;
            
            // Add event information to a log (displayed in the TextArea).

            public function collectionEventHandler(event:CollectionEvent):void 
            {
                switch(event.kind) 
                {

                    case CollectionEventKind.ADD:
                        addLog("Item "+ event.location + " added");
                        break;
                    case CollectionEventKind.REMOVE:

                        addLog("Item "+ event.location + " removed");
                        break;
                    case CollectionEventKind.REPLACE:

                        addLog("Item "+ event.location + " Replaced");
                        break;
                    case CollectionEventKind.UPDATE:

                        addLog("Item updated");
                        break;
                }
            }
            // Helper function for adding information to the log.
            public function addLog(str:String):void 
            {

                log.text += str + "\n";
            }
            
            // Add a person to the ArrayCollection.
            public function addPerson():void 
            {

                ac.addItem({first:firstInput.text, last:lastInput.text,
                        email:emailInput.text});
                clearInputs();
            }
            
            // Remove a person from the ArrayCollection.

            public function removePerson():void 
            {
                // Make sure an item is selected.
                if (dg.selectedIndex >= 0) 
                {

                    ac.removeItemAt(dg.selectedIndex);
                }
            }
            
            // Update an existing person in the ArrayCollection.
            public function updatePerson():void 
            {

                // Make sure an item is selected.
                if (dg.selectedItem !== null) 
                {
                    ac.setItemAt({first:firstInput.text, last:lastInput.text,
                        email:emailInput.text}, dg.selectedIndex);
                }

            }
            
            // The change event listener for the DataGrid.
            // Clears the text input controls and updates them with the contents
            // of the selected item.
            public function dgChangeHandler():void 
            {

                clearInputs();
                firstInput.text = dg.selectedItem.first;
                lastInput.text = dg.selectedItem.last;
                emailInput.text = dg.selectedItem.email;
            }
            
            // Clear the text from the input controls.

            public function clearInputs():void 
            {
                firstInput.text = "";
                lastInput.text = "";
                emailInput.text = "";
            }

        
        ]]>
    </mx:Script>
    
    <!-- The ArrayCollection used by the DataGrid and ComboBox. -->
    <mx:ArrayCollection id="ac"

            collectionChange="collectionEventHandler(event)">
        <mx:source>
            <mx:Object first="Matt" last="Matthews" email="matt@myco.com"/>

            <mx:Object first="Sue" last="Sanderson" email="sue@myco.com"/>
            <mx:Object first="Harry" last="Harrison" email="harry@myco.com"/>

        </mx:source>
    </mx:ArrayCollection>

    <mx:Panel title="Master-Detail View" width="100%">
        
        <mx:DataGrid width="100%" id="dg" dataProvider="{ac}"

                change="dgChangeHandler()">
            <mx:columns>
                <mx:DataGridColumn dataField="first" headerText="First Name"/>

                <mx:DataGridColumn dataField="last" headerText="Last Name"/>
                <mx:DataGridColumn dataField="email" headerText="Email"/> 
            </mx:columns>

        </mx:DataGrid>
        
        <!-- Form for data to add or change in the ArrayCollection. -->
        <mx:Form label="test" width="100%">

           <mx:FormItem label="First Name" width="100%">
                <mx:TextInput id="firstInput" width="100%"/>

           </mx:FormItem>
           <mx:FormItem label="Last Name" width="100%">
                <mx:TextInput id="lastInput" width="100%"/>

           </mx:FormItem>
           <mx:FormItem label="Email" width="100%">
                <mx:TextInput id="emailInput" width="100%"/>

           </mx:FormItem>
        </mx:Form>
    
        <mx:ControlBar horizontalAlign="center">
            <!-- Buttons to initiate operations on the collection. -->

            <mx:Button label="Add New" click="addPerson()"/>
            <mx:Button label="Update Selected" click="updatePerson()"/>

            <mx:Button label="Remove Selected" click="removePerson()"/>
            <!-- Clear the text input fields. -->

            <mx:Button label="Clear" click="clearInputs()"/>
        </mx:ControlBar>

    </mx:Panel>

    <!-- The application displays event information here -->
    <mx:Panel title="Change log" width="100%" height="125">        
        <mx:TextArea id="log" width="100%" height="100%"/>

    </mx:Panel>    

</mx:Application>

Result

AlertThis content requires Flash

Download the free Flash Player now!

Get Adobe Flash Player

To view the full source, right-click the Flex application and select View Source from the context menu.


For more information

About the author

Aral Balkan acts and sings, leads development teams, designs user experiences, architects rich Internet applications, and runs OSFlash.org, the London Macromedia User Group, and his company, Ariaware. He loves talking design patterns and writing for books and magazines. He also authored Arp, the open-source RIA framework for the Flash platform. Aral is generally quite opinionated, animated, and passionate. He loves to smile, and can even chew gum and walk at the same time.