counter for wordpress

tutorials

Video Tutorial: Building a List with realtime data using Flash Catalyst, Photoshop and Flash Builder 4

Check out the 4 part video tutorial on building a DataList which uses realtime data using an Adobe Photoshop PSD, Flash Catalyst & Flash Builder 4 in a single work flow.

Check out the tutorial

PART I | PART II | PART III | PART IV

This series also marks the launch of my video blog – The Flexgeek Show. All my video tutorials will be henceforth posted in The Flexgeek Show. The blog will also feature under the hood sessions on various aspects of the Adobe Flash Platform tools by the flex engineering team, videos of Adobe events, customer interviews and many more fun stuff. Please do add http://broadcast.flexgeek.in to your bookmarks.

Tips & Tricks : AdvancedDataGrid – grouping & summary rows

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

Tutorial: Using same itemRenderer for multiple columns

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

Tips & Tricks – ItemEditors – II

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

Tips & Tricks : itemEditors – I

Alex has written two wonderful posts in his blog about working with itemRenderers. Along with itemRenderers another extremely useful feature in flex is itemEditors. itemEditors provide a highly efficient and clean way of providing custom editors for editing data in components like List and DataGrid.

Take this example: You have a Datagrid with two columns (Product, Available and Order Qty). Avaliable & Order Qty columns contain numeric data. You want to allow the user to make an order by selecting the Order Qty column by entering a value for the number of pieces he wants to order in the column.

Option 1: You can simply pop the default itemEditor of a Datagrid / List, which is a TextInput where the user can key in the number.
Option 2: You can pop a custom itemEditor.In this case, using a NumericStepper makes a lot of sense because it lets the user increment / decrement a value and also allow him to type in just like in a textinput.

I have used Option 2, to implement the solution.

So, Why itemEditors and not itemRenderers?
You can set a NumericStepper as an itemRenderer and set the rendererIsEditor property to true. But in that case the renderers are pre-created, they are *always* displayed evcen when you are not editing it and lastly, you have to write your own logic to persist the data after editing the cell. (That surely seems like more work than using itemEditors for our current problem.)

Lets Get back to itemEditors - Take a look at the example attached along with this post which uses a NumericStepper as its itemEditor. You can see that the NumericStepper is popped when you click on the cell in the Order Qty column and the editor is destroyed when you click on anywhere else / change the focus. Also note that the value that you entered / stepped is now committed and the DataGrid display is updated.

Lets do a little digging into the code :)
As you can see, there is *very little* code that is written to implement this solution.

Step 1 – Set up the data: (see inline code comments)

//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 array with dummy product names
var prodarray:Array = ['Apple','Orange','Peach','Grapes','Guava','Mango','Raspberry','Strawberry','Watermelon','Passionfruit']
//Create an arraycollection
arr = new ArrayCollection()
//Loop to create 10 records
for(var i:int=0;i<10;i++)
{
//create a random number
var rnd:Number = Math.round(Math.random()*100);
//Create an object to insert into the array collection
var obj:Object = {value:rnd, disp:prodarray[i],order:0}
//Add the object to array collection
arr.addItem(obj)
}

}

Step 2: Create the Datagrid and set up the itemEditor.

The following lines of code create an instance of Datagrid with 3 columns, and we set the itemEditor and editorDataField properties to the third column. (See inline comments)

One important point to be remembered here. The DataGrid or List always looks for the default property text on the itemEditors unless you specify the editorDataField property to the appropriate value. In this case editorDataField will be value since we will be altering the value property when we increment / decrement a NumericStepper. If we were to use a TextArea, the property should be set to text. If you forget to set this property, then prepare yourself for some erratic behavior :)

<!– DataGrid Instance, dataProvider is bound to ‘arr’- the arraycollection. –>
<mx:DataGrid editable=”true” id=”datagrid” x=”56″ y=”104″ height=”176″ width=”317″ dataProvider=”{arr}”>
<mx:columns>
<mx:DataGridColumn headerText=”Product” dataField=”disp”/>
<mx:DataGridColumn headerText=”Available” dataField=”value”/>
<!– 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>

Step 3: Create the custom itemEditor

I have created a CustomNumericStepper class which extends from NumericStepper. (CustomNumericStepper.as). This class contains just two properties, the maximum and the stepSize. The maximum is set to 150, assuming that we will *not* be stocking more than 150 fruits of each type (well, we will change this assumption soon, accommodating a more realistic calculation, but lets keep it this way for the sake of simplicity :) )

package
{
import mx.controls.NumericStepper;

public class CustomNumericStepper extends NumericStepper
{
public function CustomNumericStepper():void
{
super();
//Set the properties
stepSize=1;
maximum=150;
}
}
}

Note: I chose to write this as a .as file, you could very well use an MXML component to achieve the same results.

We are all set to go!

View the Sample | Download Source

and right click on the application to view / download the full source.

Coming up next: Doing more with itemEditors – applying formatters & validators to itemEditors

Alex Harui’s Flex Blog

Alex Harui from the Flex SDK Engineering team of Adobe USA has started a blog. The blog can be accessed at the following location.

http://blogs.adobe.com/aharui/

The Blog contains some extremely easy to follow explanations, some great code snippets and examples.Alex is some one almost every flex engineering team guy at Adobe looks upto for their flex related issues.