Learning Flex Basics (Part 3) : Working with Containers
In this tutorial you will work with navigation and layout containers to create an application with multiple views. You learn to use several layout containers and the Repeater class, which iterates over an array of data. You also learn how to handle events for items that a Repeater class generates.
This tutorial is the first part in a four-part series written by Robert Crooks of the Macromedia Customer Training group:
- Learning Flex Basics (Part 1): Creating Your First Flex Application
- Learning Flex Basics (Part 2): Creating a Flex Calculator
- Learning Flex Basics (Part 4): Working with Data Models
If you like what you see and want to get more experience with Flex, Macromedia Customer Training offers Fast Track to Macromedia Flex, a two-day onsite training course to jump-start Flex development in your organization. Now let's get started!
What you will learn
- How to use the Application tag.
- How to use the TabNavigator.
- How to use the ViewStack.
- How to use the LinkBar.
- How to use a Panel container.
- How to use the HBox.
- How to use the VBox.
- How to use the Form container.
- How to use the Tile container.
- How to use the Repeater class.
- How to use Label controls.
- How to use Button controls.
- How to create an array in ActionScript.
- How to create event handlers for events on repeated items in ActionScript.
Requirements
To complete this tutorial you will need to install the following software and files:
Macromedia Flex
(Installed and running on any server and platform supported by Flex. Note that the Flex trial is available on CD from the Macromedia store for $8.99. To learn more about the Flex trial, please read the Flex Frequently Asked Questions.)
Dreamweaver MX 2004 or a text editor that you can use to write XML and ActionScript code (a basic text editor such as Notepad is adequate)
Solution files for the tutorial:
- containers.mxml from the zip for this article.
Prerequisite knowledge:
- Read A Brief Overview of Flex.
- You must know how to browse a Flex application.
- You should have completed Learning Flex Basics (Part 1): Creating Your First Flex Application and Learning Flex Basics (Part 2): Creating a Flex Calculator or have a basic understanding of how Flex applications work.
Building the Application
The application is simple. The tutorial focuses on learning how to use navigation and layout containers. You will create a global navigation system for two main views using the TabNavigator container. In one of the main views you use the LinkBar and ViewStack navigator containers to create a local navigation system for two secondary views.
In the views, you use a variety of layout containers: Panel, HBox, VBox, Form, and Tile. You also learn how to use the Repeater class to iterate over a data set, and to create event handlers for the repeated items.

Figure 1. Form View

Figure 2. Tile View

Figure 3. Pseudo Bar Chart
Create the Application Object
To begin any Flex application, start with an XML declaration and an Application
block. The Application
tag will include a namespace declaration for the
MX class library: xmlns:mx="http://www.macromedia.com/2003/mxml"
. The mx prefix is used with all tags for
this library.
- Create a new file and save it as calculator.mxml in the flex_tutorials directory.
-
At the beginning of the file, insert the XML declaration:
<?xml version="1.0">
-
After the XML declaration, add an
Application
tag with the MXML namespace:<mx:Application xmlns:mx="http://www.macromedia.com/2003/mxml"> </mx:Application>
Create a Data Array
In the first tutorial you learn how to create an Array using tag syntax. Here you create one in ActionScript.
-
Inside the Application block, Script block with a CDATA wrapper to prevent the XML parser from trying to interpret the script as XML code:
<mx:Script> <![CDATA[]]> </mx:Script>
-
Inside the Script block, declare a variable called
myArray
of typeArray
, and set the values of the array items as[0,1,2,3,4,5,6,7,8,9]
:var myArray=[0,1,2,3,4,5,6,7,8,9];
Add a TabNavigator Container for Global Navigation
The TabNavigator container automatically creates
navigation aids for layout containers nested inside it based on their label
values.
-
After the Script block, add a TabNavigator container with margin, height, and width values as follows:
<mx:TabNavigator id="tabNav" marginLeft="10" marginTop="20" height="500" width="500"> </mx:TabNavigator>
Add an HBox Layout and Panel Containers for Main Views
The Flex class library contains a number of layout container classes for arranging contents visually on the screen. Here you use two of them for the main navigation views:
- HBox layout container lays out its contents in a row
- Panel container (also used in the first two tutorials), lays out contents horizontally or vertically, and provides a title bar
For the Panel, use data binding to link the height of the Panel container to the height of the TabNavigator container. This is a useful technique for creating relative sizing and minimizing hard-coded sizes that would be tedious to maintain in later UI makeovers or in porting the application to a different display device. You achieve data binding here through curly braces: { and }. The curly braces indicate that the Flex compiler should evaluate the contents inside as an ActionScript expression or variable.
-
Inside the TabNavigator container block, add an HBox container block with the label "View 1: Form/Tile":
<mx:HBox label="View 1: Form/Tile">. </mx:HBox>
-
After the HBox container block, add a Panel container with the label View 2: Pseudo Bar Chart, and
id
,height
, andtitle
properties as follows:<mx:Panel id="barPanel" label="View 2: Pseudo Bar Chart" title="Pseudo Bar Chart" height="{.9*tabNav.height}"> </mx:Panel
Add a ViewStack, LinkBar, and Panel Containers for Secondary Views
The base class for the TabNavigator container is the ViewStack navigator
container, which contains an array of containers and lets yo manage
navigation between them through either the selectedIndex
or selectedItem
property
(the first references a container by its position in the array, the second
by its id value). The TabNavigator container extends the ViewStack class,
and so has its ViewStack "built-in"; other navigation
containers use a separately defined ViewStack container as a dataProvider,
but still provide the transparent handling of navigation.
The LinkBar navigator container has a direction property that you can set to horizontal or vertical, making it useful for either global or section navigation; here you use it for the latter.
-
Inside the HBox container, add a ViewStack container with the id vStack :
<mx:ViewStack id="vStack"> </mx:ViewStack
-
Before the ViewStack container, but still inside the HBox container, add a LinkBar container with a dataProvider bound to the ViewStack container and direction attribute set to vertical:
<mx:LinkBar dataProvider="{vStack}" direction="vertical"/>
-
Inside the ViewStack container, add two Panels, the first has both
title
andlabel
properties set to Form; the second hastitle
andlabel
set to Tile and anid
of tilePanel:<mx:Panel title="Form" label="Form"> </mx:Panel> <mx:Panel id="tilePanel" title="Tile" label="Tile"> </mx:Panel>
- Save the file and browse it. Click the two tabs and the two links of the LinkBar container to see the automatic handling of navigation. Also try the browser's back and forward buttons; the navigation containers tie navigation events to the browser's history so that the back and forward buttons work just as they would if these were normal web pages.
Add a Form Container
The navigation of our simple application is now complete, and for the rest of the tutorial you focus on the use of layout containers. First, you create a Form container, which automatically arranges form controls and also provides some aids for handling the processing of form data (which you won't use here, but are straightforward and covered in the Flex documentation). You can use ordinary event handlers for form data also, as you do in this exercise.
The Form works with two nested container classes:
- FormHeading: Creates one or more headings (this is optional - you can use Labels as well)
- FormItem: Creates labels for a control or a group of controls
Inside the Form, you use a ComboBox, similar to an HTML select control. The ComboBox is covered in more detail in Learning Flex Basics (Part 1): Creating Your First Flex Application. The ComboBox items are generated from an array of simple values or objects; here, you use the array you created in the Script block earlier.
You also create a ControlBar container in this section. A ControlBar is an optional footer container for a Panel with a horizontal layout.
-
Inside the Panel with the title "Form," add a Form container:
<mx:Form> </mx:Form>
-
Inside the Form, add a FormHeading with the label My Form:
<mx:FormHeading label="My Form"/>
-
After the FormHeading, add a FormItem container block with the label Pick a Number:
<mx:FormItem label="Pick a Number"> </mx:FormItem>
-
Inside the FormItem, add a ComboBox with the
id
of myCombo and the dataProvider property bound tomyArray
:<mx:ComboBox id="myCombo" dataProvider="{myArray}"/>
-
After the Form container, but still inside the Panel, add a ControlBar container:
<mx:ControlBar>
</mx:ControlBar> -
Inside the ControlBar container, add a Label whose text is the string "You chose: " joined to a binding to the
selectedItem
property of the ComboBox:<mx:Label text="You chose: {myCombo.selectedItem}"/>
- Save the file and browse it to see the form; select an different item in the ComboBox to see the Label in the ControlBar container change.
Add a Tile Layout Container and Populate It Using a Repeater
For the second view in the first main view, you use a Tile layout container, which lays out child items in rows or columns depending how the direction property is set (the default is rows). The Tile container fits items as well as it can with the space available, wrapping rows or columns as necessary.
You can enter the child elements of the Tile container manually, but the more typical use case for the container is where it will contain an a set of items that are generated by iterating over an array of data whose length may change over time, or is not known until runtime, because the data is obtained from an external source.
You iterate over a data array using the Repeater class, which takes an array
as its dataProvider. During the iteration, the currentIndex
of
the array and the currentItem
of
data are available to you programmatically. In this exercise you generate
VBox containers that contain a Label; the VBox container is similar to the
HBox container you used earlier, but arranges its children vertically rather
than horizontally.
For runtime events, in addition to the properties of the generated items,
you can access the original data item used to generate it through the getRepeaterItem()
method
of the target
property of the event
object; the
target is the object on which the event occurred. In this exercise, you handle
the event mouseDown
over
repeated items.
-
Inside the Panel with the title "Tile," add a Tile container with a width of 400:
<mx:Tile width="400"> </mx:Tile>
-
Inside the Tile block, add a Repeater with
id
of myRep and the dataProvider bound to myArray:<mx:Repeater id="myRep" dataProvider="{myArray}"> </mx:Repeater>
-
Inside the Repeater block, add a VBox container with
borderStyle
of solid and themouseDown
event set to call a function calledsetStatus()
, passingevent.target.getRepeaterItem()
:<mx:VBox borderStyle="solid" mouseDown="setStatus(event.target.getRepeaterItem())"> </mx:VBox>
-
Inside the VBox container, add a Label with the
text
property set toindex: {myRep.currentIndex} - item: {myRep.currentItem}
:<mx:Label text="index: {myRep.currentIndex} - item: {myRep.currentItem}"/>
-
Inside the script block at the top of the application, add function block for the
setStatus()
function; the function takes a parameter called item of type Number, and returns nothing:function setStatus(item:Number):Void { }
-
Inside the function block, add a single line that sets the status property of the surrounding Panel to
"Item: "+item
:tilePanel.status="Item: "+item;
Note: Remember that the item passed to the function is the original data item associated with the repeated object where the event occurred.
- Save the file and browse it. Click the repeated VBox containers to see the associated data displayed in the Panel container status area.
Create a Pseudo Bar Chart Using a Repeater and VBox Containers
In the final part of this tutorial, you deal with no new Flex classes, but instead put the VBox container to a different use: simulating a bar chart, to get a sense of the flexibility of containers.
You also learn how to change properties of repeated items at runtime. The key to this is
knowing how to access the repeated items by id. All id
values in an application must be
unique, so if you set the id
of a repeated item to a value like "myBox," myBox becomes an
array whose elements are the id
values of the items. You can then access the properties
of the ith item through myBox[i]
.
To loop over all the repeated items, loop over the id
array:
for (var i:Number=0;i<myBox.length;i++) { [do something to mybox[i]...] }
-
Inside the Panel container with the id of "barPanel," add an HBox container with height bound to 80% of the surrounding Panel's height, and contents vertically aligned to the bottom:
<mx:HBox height="{.8*barPanel.height}" verticalAlign="bottom"> </mx:HBox>
-
Inside the HBox container, add a Repeater object with the id "barRep" and the dataProvider bound to myArray:
<mx:Repeater id="barRep" dataProvider="{myArray}"> </mx:Repeater>
-
Inside the Repeater object, add a VBox container with an
id
of vBar" abackgroundColor
of 0x99CCCC, height set to 20 times thecurrentItem
of the Repeater, and contents horizontally aligned to the center:<mx:VBox id="vBar" backgroundColor="0x99CCCC" height="{20*barRep.currentItem}" width="40" horizontalAlign="center"> </mx:VBox>
-
Inside the VBox container, add a Label whose text property is bound the currentItem of the Repeater object:
<mx:Label text="{barRep.currentItem}"/>
-
After the HBox container, but still inside the Panel container, add a ControlBar container:
<mx:ControlBar> </mx:ControlBar>
-
Inside the ControlBar, add two Buttons, one with the label Scale Up and a click event that calls a function called
scaleUp()
, the other with the label Scale Down and a click event that callsscaleDown()
:<mx:Button label="Scale Up" click="scaleUp()"/> <mx:Button label="Scale Down" click="scaleDown()"/>
-
In the Script block, add the
scaleUp()
function block, the function takes no parameters and returns nothing:function scaleUp():Void { }
-
Inside the function block, create a for loop that loops over the
vBar
array :for (var i:Number=0;i<vBar.length;i++) { }
-
Inside the for loop, set the height of each
vBar
item to twice its current height:vBar[i].height=vBar[i].height*2;
-
Inside the function block, create a for loop that loops over the
vBar
array :for (var i:Number=0;i<vBar.length;i++) { vBar[i].height=vBar[i].height*2; }
-
Add the
scaleDown()
function, which is identical toscaleUp()
except that it sets eachvBar
height to half its current value:function scaleDown():Void { for (var i:Number=0;i<vBar.length;i++) { vBar[i].height=vBar[i].height/2; } }
-
That's the end of the exercise. Save the file and browse it; try the buttons to see the bars in the graph scaled up and down.
Complete Code Listing for containers.mxml
<?xml version="1.0"?> <mx:Application xmlns:mx="http://www.macromedia.com/2003/mxml" > <mx:Script> <![CDATA[ // data array var myArray=[0,1,2,3,4,5,6,7,8,9]; // handler for tile function setStatus(item:Number):Void { tilePanel.status="Item: "+item; } function scaleUp():Void { for (var i:Number=0;i<vBar.length;i++) { vBar[i].height=vBar[i].height*2; } } function scaleDown():Void { for (var i:Number=0;i<vBar.length;i++) { vBar[i].height=vBar[i].height/2; } } ]]> </mx:Script> <!-- global navigation --> <mx:TabNavigator id="tabNav" marginLeft="10" marginTop="20" height="500" width="500"> <!-- view 1 --> <mx:HBox label="View 1: Form/Tile"> <!-- section navigation --> <mx:LinkBar dataProvider="{vStack}" direction="vertical"/> <mx:ViewStack id="vStack"> <!-- form view --> <mx:Panel title="Form" label="Form"> <mx:Form> <mx:FormHeading label="My Form"/> <mx:FormItem label="Pick a Number"> <mx:ComboBox id="myCombo" dataProvider="{myArray}"/> </mx:FormItem> </mx:Form> <mx:ControlBar> <mx:Label text="You chose: {myCombo.selectedItem}"/> </mx:ControlBar> </mx:Panel> <!-- tile view --> <mx:Panel id="tilePanel" title="Tile" label="Tile"> <mx:Tile width="400"> <mx:Repeater id="myRep" dataProvider="{myArray}"> <mx:VBox borderStyle="solid" mouseDown="setStatus(event.target.getRepeaterItem())"> <mx:Label text="index: {myRep.currentIndex} - item: {myRep.currentItem}"/> </mx:VBox> </mx:Repeater> </mx:Tile> </mx:Panel> </mx:ViewStack> </mx:HBox> <!-- view 2 --> <mx:Panel id="barPanel" label="View 2: Pseudo Bar Chart" title="Pseudo Bar Chart" height="{.9*tabNav.height}"> <mx:HBox height="{.8*barPanel.height}" verticalAlign="bottom"> <mx:Repeater id="barRep" dataProvider="{myArray}"> <mx:VBox id="vBar" backgroundColor="0x99CCCC" height="{20*barRep.currentItem}" width="40" horizontalAlign="center"> <mx:Label text="{barRep.currentItem}"/> </mx:VBox> </mx:Repeater> </mx:HBox> <mx:ControlBar> <mx:Button label="Scale Up" click="scaleUp()"/> <mx:Button label="Scale Down" click="scaleDown()"/> </mx:ControlBar> </mx:Panel> </mx:TabNavigator> </mx:Application>
Where to Go from Here
Continue on to the following tutorials to learn more:
- Learning Flex Basics (Part 1): Creating Your First Flex Application
- Learning Flex Basics (Part 2): Creating a Flex Calculator
- Learning Flex Basics (Part 4): Working with Data Models
If you like what you see and want to get more experience with Flex, Macromedia Customer Training offers Fast Track to Macromedia Flex, a two-day onsite training course to jump-start Flex development in your organization. You should also look at the informative set of sample applications in included with Flex; these illustrate the use of many Flex features.