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.
Do check out my Simple Gantt chart built on AdvancedDataGrid








June 14, 2007 - 11:06 am
Thanks Harish. Nice to see an example of the ADG.
June 15, 2007 - 6:32 pm
Just what I was looking for ! Great job. You rock
August 8, 2007 - 7:33 am
hi.
is it possible to place the hierarchical column some where else other than the first column.Flex 3 automatically places the hierarchical structure on the first column itself.
August 13, 2007 - 8:00 pm
does anyone know what the SummaryObject structure looks like? I want to create a labelfunction for a clumn that has a summary, but I want to summary to still appear.
November 14, 2007 - 3:34 am
Great tutorial – only thing im left wanting is how to auto expand the group folders. I’ll have a poke through the help docs.
November 21, 2007 - 4:44 pm
thanks for the GREAT post! Very useful…
December 19, 2007 - 4:53 pm
Oh, and did not know about it. Thanks for the information …
May 4, 2008 - 7:57 pm
Great article,
Anyone know how to change the label of the folder and more importantly display the first row of the data.
I have a db table with note records, we kep a history of the notes, the notes all have the same id, and time stamped. I call the notes back ordered by time stamp. I get an advanced data grid, with the folder(tree) names as the noteid from the db. I would like too display the first record(row) with the folder, and then if the user wants to open the folder(tree) to see the note history they can. Otherwise they can just read the latest.
Thanks in advance
July 14, 2008 - 8:02 pm
Examples don’t seem to be working
July 31, 2008 - 10:47 am
What a wonderfull example. Really U r Rocking Harish.
One thing if u mention the way to add text with summary like “Total Licenses : “
August 5, 2008 - 2:43 pm
To change the folder labels you can use groupLabelFunction property and specify a function.
Look at the adobe help file for function signature and more help in advanceddatagrid help.
August 19, 2008 - 4:11 pm
It appears that the links to the source code and example are dead.
September 10, 2008 - 3:11 pm
Hi,
AdvancedDataGrid – grouping & summary rows a great example. Could you please email me the source?
The download link is broken.
Thanks
Vimal
October 7, 2008 - 4:07 pm
Hi Nice example about AdvancedDataGrid, the download is not working. Could you pls email me the src code in zip format if possible?
Thanks
January 2, 2009 - 7:08 pm
Great example. i am trying to take it one step further. does anyone know how to handle variable tree depths?
thx
paul
February 11, 2009 - 1:48 pm
I have seen this code some where else..although explanation is goof..but its totally copy of that code..even variable names and all things.
February 11, 2009 - 2:32 pm
Hi Sachin:
By any chance, did you see this in my other blog – http://flexgeek.wordpress.com? Otherwise, it will be helpful to tell me where did u find the same code. Before making a judgement that I plagiarized the code, you must also remember that someone else can lift the code from here and post as well.
I am quite sure this code was written by me and thats the reason I approved your comment.
Cheers!
Harish
March 13, 2009 - 2:36 am
Thanks for the great code. I have been able to duplicate the process, however, am now running into a snag. Would you be able to help me use this code with an external arrayCollection as the dataProvider for the ADG.
I am trying to do the following
public var dgData:ArrayCollection;
_adg.dataProvider = dgData;
I am unable to get the datagrid to respond when I set this public variable. Do you know the process to get this working
Thanks so much for your help
Don
June 4, 2009 - 6:46 pm
Hey Harish,
I’m facing an issue to skip some rows while rendering the data using advanceddtagrid. I have requirement that I need to avoid some records based on the other column value. ie. If I have a table with the fields Name, Sex.
I should display only names who are male. Can you please send me an example if possible to my mailid.
Thanks,
Siva
June 4, 2009 - 6:55 pm
Hi Siva:
You can use a simple filterFunction on your dataProvider to filter out rows based on column parameters.
Take a look at peter’s posts on filterFunction here – blog.flexexamples.com/tag/filterfunction/
Hope that helps!
Thanks!
June 9, 2009 - 2:30 am
I did try to use the bit of the grouping and sunnimg , but for some reason , i can never get it work . The grouping wors . But Summing does not work .I think I have missed something . Cause if i do an alert of itr.current.SelectedMonthTotals I always get a blank value .
Here is what I have done .
//Make a grouping collection
mygroup=new GroupingCollection();
//Set the source to the array collection (this case dataProvider)
mygroup.source = _xlcCatalog;
//Create a new grouping
var group:Grouping = new Grouping();
group.groupingObjectFunction = grpObjFunc;
//Group on Quarter
gf = new GroupingField(”siteNumber”);
//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
//Set the dataProvider to the grouping collection
//Call validateNow() to redraw the dg.
adg.dataProvider = mygroup;
mygroup.refresh();
adg.validateNow();
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(”SelectedMonthTotals”);
//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 gf1:GroupingField = new GroupingField(”siteNumber”);
//set the summary row(s) to groupingField
gf.summaries=[sr];
mygroup.refresh();
adg.validateNow();
Grouping works fine , but Summary row does not show up . It shows up as 0 always .
private function objFunc():SummaryObject
{
var obj:SummaryObject = new SummaryObject();
obj.summary = true;
return obj;
}
private function func(itr:IViewCursor,field:String, str:String=null):Object
{
var sum:Number=0
while(!itr.afterLast)
{
var value:Number = Number(itr.current.siteNumber);
Alert.show(’value’+itr.current.siteNumber);
if(!isNaN(value))
{
sum+= value
}
itr.moveNext()
}
return sum
}
June 9, 2009 - 4:58 am
Could you pls email the source . Maybe I can take a look @ that.
June 9, 2009 - 10:54 pm
I did realize that , the sum does not work when I have XMLListCollection as the data provider source .
if i access the xml directly from the http Service it works fine .
if i do in my dataprovider for ADG as test.lastResult.root.data it works fine .
but if I do the following
inisde the event i do public function showReports(event:ResultEvent):void {
reportList = event.result as XML;
_xlcCatalog = new XMLListCollection(reportList.Product);
}
and then set xlcCatalog as the Data Provider and Group Source .
in Both Cases Grouping works but sum does not work in this case .
June 10, 2009 - 9:31 pm
Hi Harish!
It’s a nice example and very usefull.
What will I have ti change if I ‘d like to sum more than one column’s value?
I ‘ve tried that but it only keeps the sum of the last column:
//Set the summary field. The field on which the summary will be calculated.
var sf1:SummaryField = new SummaryField(”monthlyFeature”);
//Summary Function – the function that calculates the summary row display
sf1.summaryFunction = func1;
var sf2:SummaryField = new SummaryField(”monthlyFeature”);
//Summary Function – the function that calculates the summary row display
sf2.summaryFunction = func2;
var sf3:SummaryField = new SummaryField(”monthlyFeature”);
//Summary Function – the function that calculates the summary row display
sf3.summaryFunction = func3;
//set the summary rows fields property to summaryField
sr.fields = [sf1,sf2,sf3];
private function func1(itr:IViewCursor,field:String, str:String=null):Object
{
var sum1:Number=0
while(!itr.afterLast)
{
//trace(itr.current)
if(itr.current.monthlyFeature.firstEvent !=null){
var value:Number = Number(itr.current.monthlyFeature.firstEvent.duree);
if(!isNaN(value))
{
sum1+= value
}
}
itr.moveNext()
}
return sum1
}
private function func2(itr:IViewCursor,field:String, str:String=null):Object
{
var sum2:Number=0
while(!itr.afterLast)
{
//trace(itr.current)
if(itr.current.monthlyFeature.secondEvent !=null){
var value:Number = Number(itr.current.monthlyFeature.secondEvent.duree);
if(!isNaN(value))
{
sum2+= value
}
}
itr.moveNext()
}
return sum2
}
private function func3(itr:IViewCursor,field:String, str:String=null):Object
{
var sum3:Number=0
while(!itr.afterLast)
{
//trace(itr.current)
if(itr.current.monthlyFeature.thirdEvent !=null){
var value:Number = Number(itr.current.monthlyFeature.thirdEvent.duree);
if(!isNaN(value))
{
sum3+= value
}
}
itr.moveNext()
}
return sum3
}
September 14, 2009 - 12:20 pm
why validateNow is required.Could we not use validateProperties or validateDisplayList??
Thanks
Sachin Dev Tripathi
October 29, 2009 - 8:51 am
(also posted at http://forums.adobe.com/thread/514030)
Hi.
I have some data like so :
{
{ total : 300, year : 2001 }, // total for the entire year
{ total : 300, year : 2001, quarter : 1 }, // total for an entire quarter
{ total : 250, year : 2001, quarter : 1, month : 1 }, // total for a specific month
{ total : 275, year : 2001, quarter : 1, month : 2 },
{ total : 300, year : 2001, quarter : 1, month : 3 },
{ total : 300, year : 2001, quarter : 2 },
{ total : 250, year : 2001, quarter : 2, month : 4 },
{ total : 275, year : 2001, quarter : 2, month : 5 },
{ total : 300, year : 2001, quarter : 2, month : 6 },
{ total : 300, year : 2001, quarter : 3 },
{ total : 250, year : 2001, quarter : 3, month : 7 },
{ total : 275, year : 2001, quarter : 3, month : 8 },
{ total : 300, year : 2001, quarter : 3, month : 9 },
{ total : 300, year : 2001, quarter : 4 },
{ total : 250, year : 2001, quarter : 4, month : 10 },
{ total : 275, year : 2001, quarter : 4, month : 11 },
{ total : 300, year : 2001, quarter : 4, month : 12 },
}
As you can see, the aggregations are embedded in the data. Objects missing the quarter and month field are aggregations for the year, and those missing the month fields are aggregations for quarter.
The aggregations don’t follow the inbuilt aggregations of MAX, MIN AVG etc (it is a last-non-empty column, FYI). Is there a way to group this data in an AdvancedDataGrid?
Thanks.
December 27, 2009 - 5:28 am
Hi, Harish.
Congratulations for your posts.
I’m novice in Flex and I need some help. I have a ADG with state, name and trainning period for each employed from a company. I have one panel with filters (date, state, etc.) Everything is working fine… Or not… I have a slider with a range of hours. MyADG is grouping states and names (my source is an Arraycollection). I want show only totals (summaries) when the total values are between the slider range.
Can You help me, please. I need only this to finish my work.
Thank you. If you want, send me an e-mail.