Introduction
In Part 2 of the series of articles on "Flex Data Driven Controls", we learn about how to provide custom rendering to a data bound control. And we choose List.
In the previous article, Part 1 of the series, we got ourselves started with data driven controls - ComboBox and DataGrid. In this article, we will lean to cutomize the how the items are finally presented to the end user.
The source code for this article is available in the Downloads area.
Getting Started
We reuse the previous definition of UserProfile. For completeness, the definition below is re-represented below:
package com.edujinilabs.eduzine.tutorials.flex.core
{
/**
* Part of the Eduzine (http://eduzine.edujini-labs.com) Articles.
*
* Downloads available at http://downloads.edujini-labs.com
*
* (C) 2008, Edujini Labs Pvt Ltd
* http://www.edujini-labs.com
*/
public class UserProfile
{
private var _employeeID : int;
private var _employeeName: String;
private var _departmentName: String;
public function UserProfile(eid: int = 0, name: String = null, deptName: String = null)
{
this._employeeID = eid;
this._employeeName = name;
this._departmentName = deptName;
}
public function get employeeID(): int
{
return _employeeID;
}
public function set employeeID(eid: int) : void
{
this._employeeID = eid;
}
public function get employeeName(): String
{
return _employeeName;
}
public function set employeeName(name: String) : void
{
this._employeeName = name;
}
public function get departmentName(): String
{
return _departmentName;
}
public function set departmentName(name: String) : void
{
this._departmentName = name;
}
}
}
As far the user interface is concerned, we replace the ComboBox with List and remove DataGrid from the previous MXML definition. There would be a need to customize the layout a bit. The final definition looks as follows (important changes have been marked in bold):
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"
height="426" width="400" borderThickness="2" borderStyle="solid"
backgroundColor="#F0F0F0" cornerRadius="8">
<mx:Label text="Edujini™ Labs Pvt Ltd" fontSize="14" fontFamily="Georgia"
fontWeight="bold" fontStyle="normal" color="#F5A83B" left="20" top="20"/>
<mx:Label x="20" y="64" text="Edujini Team" fontFamily="Verdana" fontSize="10" fontWeight="bold"/>
<mx:List id='eList' x="20" y="90" dataProvider="{employees}" labelField="employeeName"
cornerRadius="4" width="344" height="265">
</mx:List>
<mx:Label x="20" text="© 2008, Edujini™ Labs Pvt Ltd" fontFamily="Verdana"
fontSize="10" fontWeight="bold" bottom="20"/>
<mx:Script>
<![CDATA[
import com.edujinilabs.eduzine.tutorials.flex.core.UserProfile;
import mx.collections.ArrayCollection;
[Bindable]
private var employees: ArrayCollection = new ArrayCollection(
[
new UserProfile(11, "Shake Sajan", "Product Dev"),
new UserProfile(24, "Meera", "Training"),
new UserProfile(23, "Neelam", "Training"),
new UserProfile(12, "Hari S Nair", "Product Dev"),
new UserProfile(13, "Abdul Prodhani", "Product Dev"),
new UserProfile(21, "Ashish Vaish", "Training"),
new UserProfile(10, "Gaurav Vaish", "Technology"),
new UserProfile(32, "Jagadish", "Marketing"),
new UserProfile(33, "Anshu", "Marketing"),
new UserProfile(22, "Padma Raviee", "Training"),
new UserProfile(14, "Rajesh", "Technology"),
new UserProfile(31, "Yashwanth C", "Management"),
new UserProfile(34, "Ramesh", "Finance")
]);
]]>
</mx:Script>
</mx:Application>
With this, the UI that we expect is as follows:
Flex Item Renderers
This interface is decently fine. Let's get something more out of this. How about change the UI to not only display the employees' names but also their Employee ID and the Department Name. And showing them a little formatted - say, in two lines rather than in a single line.
Adobe Flex data driven controls work internally with the so called item renderers to represent a "list of items". The external presentation may be linear, grid, tree or a combination of these.
To get started, let us define a simple renderer for our List. Modify the List definition to as follows:
<mx:List id='eList' x="20" y="90" dataProvider="{employees}" labelField="employeeName"
cornerRadius="4" width="344" height="265">
<mx:itemRenderer>
<mx:Component>
<mx:VBox>
<mx:Label text="ID: {data.employeeID}" />
<mx:HBox width="100%">
<mx:Label text="Name: {data.employeeName}" width="50%" />
<mx:Label text="Department: {data.departmentName}" width="50%" />
</mx:HBox>
</mx:VBox>
</mx:Component>
</mx:itemRenderer>
</mx:List>
The itemRenderer comprises of one VBox with two entries - a Label to display the Employee ID, and a HBox comprising of details for Employee Name and the Department Name.
Note that the itemRenderer element can contain only a definition of the Component which in turn can comprise of only one component. For example, it is not possible to have a Component with two Label elements directly within itself. These Labels must be enclosed in a container layout, like VBox in this case.
Also note that the controls are bount to values of the type {data.*}. data is a special variable in this case - it refers to the item being rendered. For each iteration corresponding to the entry in the dataProvider, data takes up the corresponding value. The type of the value referred to by data is same as that in the dataProvider, which in our case is com.edujinilabs.eduzine.tutorials.flex.core.UserProfile.
The UI expected is as below:
Flex Item Editors
Let's further fancy the UI and give the HR department an ease to be able to edit the details inline. When the HR personnel clicks on any entry, it should get into the edit mode and display the items as below:
- Employee ID: Must be shown in a
Label. - Employee Name: Must be shown in a
TextInput, so that it may be updated. - Employee ID: Must be shown as a
ComboBox, with a list of options available.
Now that we already know how to data-bind the controls, we can directly jump on to looking at the updated List definition in the MXML:
<mx:List id='eList' x="20" y="90" dataProvider="{employees}" labelField="employeeName"
cornerRadius="4" width="344" height="265" editable="true" itemEditEnd="event.preventDefault()">
<mx:itemRenderer>
<mx:Component>
<mx:VBox>
<mx:Label text="ID: {data.employeeID}" />
<mx:HBox width="100%">
<mx:Label text="Name: {data.employeeName}" width="50%" />
<mx:Label text="Department: {data.departmentName}" width="50%" />
</mx:HBox>
</mx:VBox>
</mx:Component>
</mx:itemRenderer>
<mx:itemEditor>
<mx:Component>
<mx:VBox>
<mx:Label text="ID: {data.employeeID}" />
<mx:HBox width="100%">
<mx:TextInput text="{data.employeeName}" width="50%" />
<mx:ComboBox width="50%" selectedItem="{data.departmentName}">
<mx:dataProvider>
<mx:String>Product Dev</mx:String>
<mx:String>Training</mx:String>
<mx:String>Technology</mx:String>
<mx:String>Finance</mx:String>
<mx:String>Management</mx:String>
</mx:dataProvider>
</mx:ComboBox>
</mx:HBox>
</mx:VBox>
</mx:Component>
</mx:itemEditor>
</mx:List>
The updates in the code, now, must be self explanatory. You would also notice alternate form of specifying the dataProvider for the ComboBox. If you select any entry in the list, it must get into the edit-mode. The expected UI is as given below:
So, we seem to have got everything... except that the names / department names, if updated, do not effect the original items (the model). We shall explore this in our next article.
Summary
In this article, we learnt to:
- Use Flex Item Renderers in data driven controls to create a rich UI to render the business objects.
- Use Flex Item Editors to edit the business objects. We have left the task of updating the business objects to the next article.
