Harish Sivaramakrishnan

Platform Evangelist @ Adobe

Author Archive

Task Scheduler Chart using AdvancedDataGrid (moxie)

31 comments

Soure now available here!

Few days back I had posted an example of a Gantt chart component developed using the AdvancedDataGrid of moxie. I was playing around with the component for the horizontal scrolling performance analysis and finally ended up writing this small component.

This is a simple engineering work items display which shows the tasks for each engineering role with drill down capabilities. Double Clicking the quarter information column will drill down the data for that column (double click to collapse) . Clicking on the month info will get you the day-wise breakdown of the tasks. (double click the top column to collapse). I intend to develop this as a full fledged component once I am done with my current commitments at work. Watch out this space for more updates and also source code. For the time being, check out the application here.

download Download Source


Written by vodka

June 28th, 2007 at 8:12 am

Posted in flex

Tips & Tricks : AdvancedDataGrid – grouping & summary rows

28 comments

This is the first among the series of articles that I intend to write about the new AdvancedDataGrid control of Flex 3.0 (moxie). You would require Flex 3 beta 1 to compile and run this example. If you dont have moxie yet, download it here

Displaying grouped (hierarchical) data & summary rows in AdvancedDataGrid

One of the key features of the new AdvancedDataGrid (will be referred to as ADG from hereafter) is its inbuilt capablility to display hierarchical data. This is made possible through the new set of collections classes that have been added. The following example helps you learn two things:

  • How to create a grouped data from the flat data that is supplied to ADG
  • Create summary rows based on the data.

Lets now look at the example :)

The example in this article has an ADG which display the quarterly revenue details of companies and the number of licences sold by each one of them stored as an XMLList. This XMLList is supplied as the dataProvider for the ADG. (This is all similar to what you would do in the DataGrid).


Now, Lets try and group this data based on the field quarter. Lets look at the code that will let us do that

//Make a grouping collection
var mygroup:GroupingCollection=new GroupingCollection();
//Set the source to the array collection (this case dataProvider)
mygroup.source = colgrouped_adg.dataProvider;
//Create a new grouping
var group:Grouping = new Grouping();
//Group on Quarter
var gf:GroupingField = new GroupingField(“Quarter”);
//Set the fields to the grouping
group.fields = [gf];
//Finally, Set the group to the grouping property of groupedCollection
mygroup.grouping = group;
//Refresh the group
mygroup.refresh();
//Set the dataProvider to the grouping collection
colgrouped_adg.dataProvider = mygroup
//Call validateNow() to redraw the dg.
colgrouped_adg.validateNow()

The steps are as follows:

  • create a grouping collection
  • set the source to a flat collection (this case the ADG DataProvider)
  • create an instance of grouping
  • create a grouping field and pass the field that you want the data to be grouped on
  • set the fields property of the grouping to the groupField
  • set the grouping property of the grouping collection to grouping instance
  • refresh the grouping collection
  • set the dataProvider of ADG to the grouping collection
  • call validateNow() on ADG to update the display


Now, Lets write some code to calculate the summary of the total number of licences sold by *ALL* companies. Here we go!

var sr:SummaryRow = new SummaryRow();
//Set the summaryObjectFunction
//This function tells ADG to add a summary row in addition to the existing data
sr.summaryObjectFunction = objFunc;
//Set the summary field. The field on which the summary will be calculated.
var sf:SummaryField = new SummaryField(“Licenses”);
//Summary Function – the function that calculates the summary row display
sf.summaryFunction = func;
//set the summary rows fields property to summaryField
sr.fields = [sf];
//Place the summary row (Last means data First, summary Last!)
sr.summaryPlacement = “last”;
//Group on Quarter
var gf:GroupingField = new GroupingField(“Quarter”);
//set the summary row(s) to groupingField
gf.summaries=[sr]

Thats fairly straight forward. Here are the steps you need to follow to get a summary row in your ADG.

  • Create a summary row instance
  • Set the summaryObjectFunction to include a summary in your ADG data
  • Create a summary field, the field on to which the summary calculation formula needs to be applied.
  • Write a summary function which contains the logic to calculate the summary
  • set the summaryField to the fields propety of summary row
  • Define summaryPlacement “First / Last” First will put summary before data, last will add it after the data
  • Finally set the summary rows to the groupingField.

The SummaryObjectFunction looks like this: (This method returns a SummaryObject)

private function objFunc():SummaryObject
{
var obj:SummaryObject = new SummaryObject();
obj.summary = true;
return obj;
}

Finally, the summary function. summaryFunction accepts 3 parameters (its a callback, you may never have to pass params to it, but be sure that you write the signature correctly) an iterator,a field and an operation. (operations include build-in methods like ADD).

private function func(itr:IViewCursor,field:String, str:String=null):Object
{
var sum:Number=0
while(!itr.afterLast)
{
//trace(itr.current)
var value:Number = Number(itr.current.Licenses);
if(!isNaN(value))
{
sum+= value
}
itr.moveNext()
}
return sum
}

Thats it! We are done and what we get will look like this :)

I have included the sample application as well as full source code for this example. Do take a look at it. I hope this one was useful for all those who are exploring the new ADG. Do look out for more tutorials on this topic.

Download Source

Do check out my Simple Gantt chart built on AdvancedDataGrid

Written by vodka

June 14th, 2007 at 8:03 am

Simple GanttChart using AdvancedDataGrid of Flex 3.0 (Moxie)

60 comments

Update: Do check out the Flex 4 prototype of of the gantt chart here.

Flex 3.0 (Moxie) beta is out and I am sure most of you would have started playing around with the cool new features of Moxie. <mx:AdvancedDataGrid> is the new, improved DataGrid – a super cool component in moxie. Its a very exciting moment for me because I was part of the engineering team that designed and developed this control :) . I spent a few hours yesterday to see if I can use this control to write a simple Gantt chart, given the fact that the AdvancedDataGrid lets you have column spanned itemRenderers , groupedColumns and hierarchical display. I took a similar approach to what Doug had done in his example of a gantt chart.

This is what I got!! :)

ADG-Gantt sample

This is a rough prototype that I wrote and I sure dint spend much time designing this application. I will try and get this one as a component when I have a little more of free time.

Things I loved about AdvancedDataGrid doing this small app :)

  • AdvancedDataGrid Rocks!
  • The new groupingCollection APIs make hierarchical display of data Child’s play
  • The rendererProviders property and the column spanning lets you customize itemRenderers in a much advanced way than DataGrid
  • <mx:AdvancedDataGridColumnGroup> lets you group the columns seamlessly!

The horizontal scrolling is a little slow, but we are sure working on it to get it a lot faster than what it is now! (hey, its just a beta!)

You can download the source code from here.[Adobe Share] If you cant figure out much from the data, its just a timeline of set of tasks and their respective percentages. Red shows delayed. Orange shows delayed start, green shows timely completion, grey - not yet started and blue – in progress.

The code that I have written requires many rounds of cleaning up before I can share it publicly :p (I will do that soon!). In the meanwhile, do check this space for a new series of tips & tricks and tutorials on working with the new AdvancedDataGrid.

All of ya keep flexing your “moxie” till then!

Written by vodka

June 13th, 2007 at 12:29 pm

Tips & Tricks – adding a combobox to a datagrid header as headerRenderer

16 comments

I am sure many of you would have tried dropping a ComboBox as a headerRenderer to a DataGrid. Well, if you try to directly drop in a ComboBox you will get an RTE and the ComboBox just doesn’t work! I got this request from one of the flex users here that they need to drop a ComboBox on a datagridcolumn to provide a UI for filtering the data in the datagrid.

After looking at the code for a while, I figured out that the set data method of the combobox checks if it is dropped in as an itemRenderer and what’s more, it sets the data irrespective of whether the value recieved in the set data is a datagrid column or not. In the case of dropping the ComboBox, the data setter sets the data to the DataGridColumn and when the program progresses it throws an RTE which says it couldnt find the property name on the headerRenderer instance.

The solution:

I subclassed the ComboBox control to make MyComboBox and wrote an override for the data Setter. I just added the following type check before the data setter in the super is called

if(value is DataGridColumn)
{
//do not call super; that is it!!
}
else
{
super.data = value
}

Thats pretty much it! The ComboBox will now correctly display in the header. I have written a simple example that has a ComboBox on the Datagrid column header which can be used to filter data. Note: I have turned off sortable columns and draggable columns in this example.

Disclaimer: This sample contains a small example of the concept, the application in itself has not been tested for bugs. People copy pasting the whole code and urged to exercise  Download Source

Written by vodka

June 7th, 2007 at 12:07 pm

Posted in flex,tips & tricks

Report: Flex APAC Seminar – 06/07

4 comments

The session on introducing ActionScript 3.0 on the Flex APAC seminar was a great success. We had 67 developers from different parts of India joining us and we had some great participation from all the members. This session was a great learning experience for me, and I enjoyed the whole 1 hour of the seminar thoroughly. Raghu joined me as a co-presenter and did a fabulous job in explaining the Flex builder debugger in just 10 minutes. Overall a wonderful start for the series and hoping to see more and more flex enthusiasts joining in for th forthcoming sessions.

Just in case if you missed the session, you can view the recording of the seminar here

Written by vodka

June 6th, 2007 at 12:18 pm

Posted in flex

APAC flex wednesdays: Inroducing AS 3.0 – Part I (06/07)

one comment

Tomorrow (06/06) we have the APAC flex wednesday where I will be talking about AS 3.0, and some key concepts of AS 3.0 for AS 2.0 as well as java developers. The talk is scheduled at 4:00PM IST. Details as follows:

APAC Flex Wednesday Series – Session II

Topic : Introducing ActionScript 3.0 (Part I)
Date : 6th June 2007
Time: 4:00 PM IST
Connect URL : http://my.adobe.acrobat.com/flexapacseminar/

See you all tomorrow!

Written by vodka

June 5th, 2007 at 2:12 pm

Posted in Uncategorized

Tips & Tricks – ItemEditors – III

9 comments

In the earlier articles (I, II) , we saw how to use itemEditors on a flex datagrid and also how to validate data that is entered in the itemEditor. Lets take the example in the previous article and improve it a little further.Lets look at the doValidation() method again: We were comparing if the entered value is greater than the upperBound and throw an error message as an Alert in the example. Flex comes with some really cool built in validators that provide a much more usable user experience than throwing an Alert box to the user when an error has occured. In this example, lets try to incorporate a NumberValidator to do the same validation that we were doing earlier using the if conditional.

The code :)

Well, things havent changed too much from our earlier example, except for the following method – doValidation()

//Validate the data entered / stepped in the itemEditor
private function doValidation(event:DataGridEvent):void
{

//Storing the selection made in the itemEditor to a variable
var selectedData:Object = CustomNumericStepper(datagrid.itemEditorInstance).value
//Store the upper bound to compare
var upperBound:Number = event.target.selectedItem.value;
//create a number validator instance. This can be extended to any validators
nv = new NumberValidator()
//specify the source – in this case the itemEditor instance
nv.source = CustomNumericStepper(datagrid.itemEditorInstance);
//Set the property to validate against. NOTE: always set this, or the validator will throw RTE
nv.property = “value”
//Set the maxvalue to the upperBound
nv.maxValue = upperBound;
//Call validate and take the return value. NOTE: validate() method sends two events valid / invalid based on the validation.
//val contains an event reference
var val:* = nv.validate(selectedData);
//check if validator returned invalid.
if(val.type == “invalid”)
{
//Prevent default action.
event.preventDefault();
}

}

So, whats different here? We are creating a new instance of a NumberValidator (nv) here. Then the source property of the validator is assigned to the control, whose data we are interested in validating. In our case, its the itemEditorInstance – the custom numeric stepper. Important point to note here – once you have set the source property, always set the “property” property (this is NOT redundant typing, there is a property called property for a validator :) ) of the validator to the property that we are validating against. Set the maxValue of the validator to the upperBound and call validate(value:Object) method on the validator. The validate() method accepts the value that we are validating.

When you run the example, you can see that the validator puts a red box around the wrongly entered field and when you move the mouse over, you can see that the error message is displayed as a red tooltip. Isn’t that cool? Do look up the documentation for the validators, there are many more properties that can be used to customize the validation parameters, error messages etc.

View Sample Application | Download Source

Written by vodka

June 4th, 2007 at 9:16 am

Posted in flex,tips & tricks

Flex bangalore user group meeting (06/01)

leave a comment

Kicking off the first Flex User Group (FUG) meeting for all the bangalore flex developers on 1st June 2007. :)
Details:

Date : 1st June 2007 (Friday)
Time : 4 pm – 5 pm
Venue: Aztecsoft,
2nd Floor Salarpuria Infinity,
#5 Bannerghatta Road
(Near Dairy circle, next to the Huge Accenture Building)

Agenda: Since this a first meeting this will be more of hanging out and setting agenda for future meetings

Looking forward to meet all those super cool uber flex dudes in bangalore tomorrow. Just confirm your attendance by replying to this thread in the flex india mailing list.

See ya all tomorrow!

Written by vodka

May 31st, 2007 at 10:00 am

Posted in flex

Tutorial: Using same itemRenderer for multiple columns

10 comments

Sample this case: You have 7 columns in your datagrid, each of which need an itemRenderer to display some conditional formatting by changing the background color based on the data belonging to that particular column. Ex – a value range of 1 – 10 will have colors varying from pale pink to red in column 1, but te same value range will display pale green to bright green in column 2 and similarly for the rest of the columns.

How will you solve this?

Solution 1: Write an itemRenderer for each column and code the logic for formatting in the indvidual renderers.

Solution 2: Write a single itemRenderer for all the columns which will achieve conditional formatting based on the columnIndex.

Practically, both this solutions can bee used but for many simple formatting cases, writing a single itemRenderer will be a much more robust solution. The example that I am illustrating below adopts the methodology mentioned in solution 2.In this simple example, I have used an itemRenderer called customItemRenderer to display different data across different columns in a DataGrid. Based on the columnIndex , the datagrid will display 3 different smiley’s in its 3 columns.

Please note that this kind of approach will be strictly tied to column indices and hence a situation where you have to use column dragging and reordering this methodology will not be useful. In the example, I have set draggableColumns=false.

Let us look in to the main application code:

<?xml version=”1.0″ encoding=”utf-8″?>
<mx:Application xmlns:mx=”http://www.adobe.com/2006/mxml” layout=”absolute” creationComplete=”populateData()” viewSourceURL=”srcview/index.html”>
<mx:Script>
<![CDATA[
//DataGrid event, fired when the itemEditing is performed
import mx.events.DataGridEvent;
//Used for populating the datagrid
import mx.collections.ArrayCollection;
//Used to display the Alert
import mx.controls.Alert;
//ArrayCollection that will hold the data
[Bindable]private var arr:ArrayCollection
private function populateData():void
{

//Create an arraycollection
arr = new ArrayCollection()
//Loop to create 10 records
for(var i:int=0;i<10;i++)
{

//Create an object to insert into the array collection
var obj:Object = {col1:i, col2:i,col3:i}
//Add the object to array collection
arr.addItem(obj)
}

}

]]>
</mx:Script>
<!– DataGrid Instance, dataProvider is bound to ‘arr’- the arraycollection. –>
<mx:DataGrid draggableColumns=”false” variableRowHeight=”true” wordWrap=”true” editable=”true” id=”datagrid” x=”56″ y=”104″ height=”176″ width=”317″ dataProvider=”{arr}” themeColor=”#CECECE”>
<mx:columns>
<mx:DataGridColumn headerText=”Column 1″ dataField=”col1″ itemRenderer=”customItemRenderer”/>
<mx:DataGridColumn headerText=”Column 2″ dataField=”col2″ itemRenderer=”customItemRenderer”/>
<mx:DataGridColumn headerText=”Column 3″ dataField=”col3″ itemRenderer=”customItemRenderer”/>

</mx:columns>
</mx:DataGrid>

</mx:Application>

There are 3 datagrid columns and each of them have the same itemRenderer assigned to them.
Well , that was fairly straight forward. Now lets take a look at the itemRenderer code. Thats where most of the action is :)

<?xml version=”1.0″ encoding=”utf-8″?>
<mx:Canvas xmlns:mx=”http://www.adobe.com/2006/mxml” width=”182″ height=”30″ implements=”mx.controls.listClasses.IDropInListItemRenderer” horizontalScrollPolicy=”off”>
<mx:Script>
<![CDATA[
import mx.controls.listClasses.BaseListData;
import mx.controls.dataGridClasses.DataGridListData;
protected var _listData:DataGridListData;
override public function set data(value:Object):void
{
setIt(value);
}
public function get listData():BaseListData
{
return _listData;
}
public function set listData(value:BaseListData):void
{
_listData = DataGridListData(value);
invalidateProperties();
}
private function setIt(value:Object):void
{
if(value && _listData)
{
if(_listData.columnIndex == 0)
{
img.source="a.gif"
}
else if(_listData.columnIndex == 1)
{
img.source="b.gif"
}
else
{
img.source="c.gif"
}
}
}

]]>
</mx:Script>
<mx:Image x=”10″ y=”6″ width=”20″ height=”20″ id=”img”/>
</mx:Canvas>

Look at the first line of the itemRenderer code. for getting access to the _listData property we have to implement the interface IDropInListItemRenderer, which has two methods.

public function get listData():BaseListData
{
return _listData;
}
public function set listData(value:BaseListData):void
{
_listData = DataGridListData(value);
invalidateProperties();
}

The _listData object holds the property columnIndex, which tells you which column does the itemRenderer belong to. Once you have the columnIndex, write your conditional logic to display corresponding data. In this case I am setting a smiley to the image control in the itemRenderer based on the columnIndex.

This can be extended to any level of conditional formatting too :)

View sample application | Download source

Written by vodka

May 30th, 2007 at 7:51 am

Posted in flex,tutorials

Tips & Tricks – ItemEditors – II

8 comments

We saw in the earlier article about using itemEditors in a flex datagrid. Now, Lets dive a little deeper into doing some more complex things with itemEditors in a flex datagrid. Before we get started, let us get introduced to the events that are most critical when we are performing an edit operation in a flex datagrid.

(Description of each of these events are available in the livedocs, readers are requested to check up)

itemEditBegin – Fired when you click on an editable cell of the datagrid (also when the editedItemPosition is set on an editable DataGrid)

itemEditBeginning - Fired when the mouse is released

itemEditEnd - Fired when the edit is committed / editor is destroyed there by terminating the edit session.

Now, Lets get back to our scenario. Let us take a simple example – We have a datagrid with a numeric stepper used as an itemEditor similar to the example stated in the part I of this article. Now, let us add an additional functionality of adding a validation to the data that gets entered in the itemEditor. Take a look at the example attached along with this post to see this in action.

Let us dig into the code now:

<mx:DataGrid editable=”true” id=”datagrid” x=”105″ y=”85″ height=”176″ width=”317″ dataProvider=”{arr}” itemEditEnd=”doValidation(event)”>
<mx:columns>
<mx:DataGridColumn headerText=”Data” dataField=”disp” editable=”false”/>
<mx:DataGridColumn headerText=”Available” dataField=”value” editable=”false”/>
<!– itemEditor is set to our class CustomNumericStepper. Always remember to set the editorDataField to the dataField on which the operation is performed–>
<mx:DataGridColumn headerText=”Order Qty” dataField=”order” itemEditor=”CustomNumericStepper” editorDataField=”value”/>

</mx:columns>
</mx:DataGrid>

when the itemEditEnd event of the DataGrid fires, we invoke a method call doValidation() which performs the validation of rhe data entered in the editor. So,whats the logic for validation? We validate if the new value that is getting entered in the column is less than or equal to the value in the available column. on fail, we will throw an alert indicating the error to the user. showError() method is used to achieve this.

//Validate the data entered / stepped in the itemEditor
private function doValidation(event:DataGridEvent):void
{

//Storing the selection made in the itemEditor to a variable
var selectedData:Object = CustomNumericStepper(datagrid.itemEditorInstance).value
//Store the upper bound to compare
var upperBound:Number = event.target.selectedItem.value;
//Compare if the entered value is > upper bound
if(selectedData > upperBound)
{
//Destroy the instance of the itemEditor by calling destroyEditor()
datagrid.destroyItemEditor()
//Call preventDefault() so that the new value is NOT committed
event.preventDefault();
//Invoke a method to display an error message
showError(upperBound);
}
}
//Display the error message
private function showError(value:Number):void
{
//Show the error message in an Alert Box
Alert.show(“Please Enter a value less than “+value)
}

So, whats doValidation() doing?

doValidation() receives the datagrid event as its parameter. The first step is to store the Object corresponding the edited item into a variable – selectedData

Now we find out what is the upper bound to validate against. This is the value in the available column for the current record that we are editing. Now we store that value to another variable – upperBound

Lets check if selectedData > uppedBound. On this condition being satisfied, we do the following steps.

Destroy the editor instance – destroyItemEditor() is called. This is to close the editor
Prevent committing of the data – event.preventDefault() is called. This prevents the default action that a particular event triggers. In this case, the committing of the data is prevented.
Finally, showError() method is called to alert the error message to the user.

There we go! We have a simple working sample of applying a validation to an itemEditor of a flex datagrid up and running.

View Sample | Download Source

Written by vodka

May 10th, 2007 at 9:40 am