Edujini Labs' Eduzine has been running a series of articles on "Exploring OOPS in JavaScript". A must read.
- Part 1: Encapsulation
- Part 2: Inheritance
- Part 3: Polymorphism
100% Tech-Zone! Some technical articles for current and future zones by Gaurav Vaish.
Edujini Labs' Eduzine has been running a series of articles on "Exploring OOPS in JavaScript". A must read.
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.
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:
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:
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:
Label.TextInput, so that it may be updated.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.
In this article, we learnt to:
Data driven controls are key to any UI toolkit, and Flex is no different.
In this article, we explore some data driven controls in Flex and look at their basic functionalities, especially the data binding and custom rendering.
In case you need a professional support on RIA, Web 2.0 and/or Flex, feel free to mail
Downloads are available in the Downloads section.
Let's take a fictitious but practical scenario. The HR department at Edujini Labs to be given a dashboard to:
To get started, let's freeze on the following UI:
The above UI can be generated using the following application definition:
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"
height="280" width="600" 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="21" y="64" text="Edujini Team" fontFamily="Verdana"
fontSize="10" fontWeight="bold"/>
<mx:ComboBox x="21" y="90"></mx:ComboBox>
<mx:DataGrid x="218" y="92" width="368">
<mx:columns>
<mx:DataGridColumn headerText="Employee ID" dataField="employeeID"/>
<mx:DataGridColumn headerText="Employee Name" dataField="employeeName"/>
<mx:DataGridColumn headerText="Department" dataField="departmentName"/>
</mx:columns>
</mx:DataGrid>
<mx:Label x="21" y="248" text="© 2008, Edujini™ Labs Pvt Ltd"
ontFamily="Verdana" fontSize="10" fontWeight="bold"/>
</mx:Application>
Note the definition of the DataGrid. It contains a bunch of DataGridColumn definitions. Each DataGridColumn has been specified a headerText - header of the column, and dataField - the property of the object whose value is to be displayed.
To model our data, let's create a class UserProfile in package, say, com.edujinilabs.eduzine.tutorials.flex.core. It comprises of the Employee ID, Employee Name and the Department Name.
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;
}
}
}
Notice that the property names have been purposely chosen to match the values of dataField of the DataGridColumn's defined earlier.
Employee list would be represented using the variable employees of type mx.collections.ArrayCollection. Ensure that it is Bindable. Finally, let's popupate it with some data, as given below. Add the code directly into the MXML Application created.
<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>
The next step is to bind the employee list to ComboBox and the DataGrid. Update the definition to as following:
<mx:ComboBox x="21" y="90" dataProvider="{employees}"></mx:ComboBox>
<mx:DataGrid x="230" y="92" width="302" dataProvider="{employees}">
Note the special syntax - the variable employees has been enclosed in the curly-braces {}. This the data-binding syntax. It is a two step process:
Bindable.After binding, the UI should appear as given below:
ComboBox Configuration
Everything looks fine except for that the ComboBox does not exactly display what we require. It displays the String representation of the UserProfile using the toString() method.
All we need to configure is the labelField of the ComboBox to tell it that it must pickup the text to be displayed to the UI from the corresponding property / field of the individual object of the collection. The default value of labelField is label.
Update the definition of the ComboBox used to as follows:
<mx:ComboBox x="21" y="90" dataProvider="{employees}"
labelField="employeeName">
</mx:ComboBox>
Voila! The UI is exactly as what we want:
In this article, we learnt to:
ComboBox and DataGrid.ComboBox.DataGrid in multiple columns.Edujini Labs announces integration of Dojo on Google Web Toolkit.
I think it's a great idea. I happened to have come across two projects on Google Code - Tatami and GWT-Dojo.
Here's the video of the "Hello, World!".
Since I am personally involved in the DWT (Dojo on Google Web Toolkit), I would be happy to report its progress so far. Besides a simple "Hello, World" application, a lot of background work has been done to talk to the native Dojo API calls.
Besides, I today outlined the life-cycle of Widget (dijit._Widget) and templated widgets (dijit._Templated).
The next steps, that I would be working on during next week (require more time because we have higher priority schedule already chalked in), is to outline the life-cycle of Container and Contained widgets.
Subsequently, we need to chalk out clear strategy on what would be written in Java and what would be passed on natively.
That's the update so far...
I had been working with WIA (for Windows XP) and WIA 2.0 (for Windows Vista) to design an application to capture images.
WIA for Windows XP works perfectly fine. And WIA 2.0 is supposed to do the same on Vista.
And then, I hit a hurdle - WIA 2.0 always gives me "0 devices" while using EnumDevices method. Finally, I hit yet another set of documents - Windows Portable Devices (WPD) here.
What the heck! Do I need to rewrite the entire application for Windows Vista? What does Microsoft want? Spend all time and money only to rewrite entire code every time a new version is released from their side?
At times, I really hate to develop any application on Windows.
The only good thing, at least at moment as it seems, is .Net Framework. At least, there I need to do minimal work. I wish it was the same case elsewhere also.