GroupingCollection with improved performance
Posted on: November 4, 2009
- In: Actionscript | Advanced DataGrid | Flex
- 43 Comments
There were some concerns over the performance of GroupingCollection class while grouping and calculating summaries.
So, a new class GroupingCollection2 is introduced in the data visualization components.
The major improvements in GroupingCollection2 are -
1. Grouping performance improved.
2. Summary calculation performance improved. Now, instead of looping over the data again and again, summaries are calculated in a single loop.
3. When using async refresh, the summaries are calculated as soon as each Group is built. Earlier, the summaries were calculated only after all the Groups have been made.
What has changed -
1. Introduced class GroupingCollection2 which replaces existing class GroupingCollection.
2. Introduced class SummaryField2 which replaces existing class SummaryField.
No no, classes GroupingCollection and SummaryField are not removed.
They will continue to exist to maintain backward compatibility.
So, you can use either GroupingCollection or GroupingCollection2 and AdvancedDataGrid will continue to work
The difference between SummaryField and SummaryField2 is -
SummaryField2 does not have “operation” and “summaryFunction” properties.
A new property “summaryOperation” in added in SummaryField2. It is an Object which takes one of the following -
* SUM, MIN, MAX, AVG or COUNT as String.
OR
* An implemtatation of mx.collections.ISummaryCalculator for calculating custom summaries.
The default value is SUM.
API changes -
1. Method refresh() has been changed in GroupingCollection2. The syntax now is –
function refresh(async:Boolean = false, dispatchCollectionEvents:Boolean = false):Boolean;
Code changes required to start using GroupingCollection2 -
1. Use GroupingCollection2 instead of GroupingCollection.
2. Use SummaryField2 instead of SummaryField.
3. Replace operation/summaryFunction in SummaryField with summaryOperation in SummaryField2.
An example is shown here:
With GroupingCollection –
<mx:GroupingCollection id="gc" source="{arr}">
<mx:Grouping>
<mx:GroupingField name="name" >
<mx:SummaryRow>
<mx:SummaryField dataField="sal"
operation="MAX" />
</mx:SummaryRow>
</mx:GroupingField>
</mx:Grouping>
</mx:GroupingCollection>
With GroupingCollection2 –
<mx:GroupingCollection2 id="gc" source="{arr}">
<mx:Grouping>
<mx:GroupingField name="name">
<mx:SummaryRow >
<mx:SummaryField2 dataField="sal"
summaryOperation="MAX" />
</mx:SummaryRow>
</mx:GroupingField>
</mx:Grouping>
</mx:GroupingCollection2>
Try it and let us know your feedback.
43 Responses to "GroupingCollection with improved performance"
This remains a Flex 4 only class right? Any chance this iwll get officially backported to Flex 3? I’m using Sreenivas’s GC2 without issues but it would be nice if it was ‘offical’ http://flexpearls.blogspot.com/2008/06/groupingcollection-with-some-better.html
So this GroupLabel I’m aware of, but its interesting how with GC (1) I saw node labels and with GC2 I didn’t. I only had the expand/collapse arrows. And my group is pretty simple as I dont use Summary Rows.
All I used to have is:
groupField1.name = “someDataField”; // this is the label in my provider
Do I need to specify columnName in ADGColumn for this to work?
Hi Sameer,
I have a page with two tabs (using view stacks) and advanced datagrid as display component. Both have same grouping fields(say A->-B->C heirarchy). And both have ‘SingleRow’ selection mode. I can move from ADG1 to ADG2 thru context menu.
My issue here is that,if I am right clicking one cell in ADG1 and going to ADG2 I want to move to same cell in the ADG2. This is posssible if I am keeping the selection mode
‘SingleCell’ for ADG2 and finding the row and column index of the selected cell and then setting the same in ADG2.
But I want to keep the selection mode as ‘SingleRow’for getting the selected row from the grid(for showing the graph for selected row) and also for opening the nodes when clicking on any cell(other than grouping field A /B/C). Otherwise this feature will fail.
Could you please help me to solve thse issues?
Also, is there any way to solve the latter issue(if we are going to set ‘singleCell’ and try to solve the first issue)?
Expecting your suggestions..
Hi Sameer,
Thanks for your quick response!!!
I have GroupingFields (A,B and C hierarchy) and 12 columns(Jan-Dec) in both ADG.So if I clicking on a cell corresponding to row C and column Jan and moving to ADG2, then same cell should be selected in ADG2(corresponding to C-Jan). As you said we cannot select single
cell if selection mode is’SingleRow’, I have to keep the selection mode as ‘SingleCell’ in ADG2. Now , I am able to point the corresponding cell in ADG2.
But, I think we will not get the grouping field values when clicking on a cell if selection mode is singleCell.
My requirement is that if I am selecting one cell(underany column) in the ADG2, I need to get the correspoding values of the grouping fields A, B and C. and 12 columns. i.e entire selecteItem of the AdvancedGrid. (for showing graphical view of the selected row)
I have tried the following code
itemClick=”adg_itemClick(event);)
private function adg_itemClick(event:ListEvent):void{
AdvancedDataGrid(event.currentTarget).selectionMode = “singleRow”;
var adgSelectedItem:Object = AdvancedDataGrid(event.currentTarget).
selectedItem;
var selectedA:String = adgSelectedItem["A"];
var selectedB:String = adgSelectedItem["B"];
var selectedA:StringselectedC = adgSelectedItem["C"];
Alert.show(“row A”+selectedA );
Alert.show(“row B”+selectedB);
Alert.show(“row C”+selectedC);
AdvancedDataGrid(event.currentTarget).selectedCells = new Array();
}
I haven’t test it completely. But facing some problems in clearing the initially selected cell (while landing to ADG2 from ADG1).
Thanks
Hey Sameer,
I’m using Advance datagrid and using combo selection to group columns. For example, If I select “Status” from drop down my grid is group by Status. So my grouping code is something like below which runs on combo selection.
var mygroup:GroupingCollection=new GroupingCollection();
mygroup.source = dominoXML.lastResult.opcenter;
var group:Grouping = new Grouping();
group.fields = [new GroupingField(groupField)];
mygroup.grouping = group;
mygroup.refresh();
Set the dataProvider to the new grouping collection
viewGrid.dataProvider = mygroup
Now I would to display total number of records from each category like below if I assume “Status” is selected in combo .
Status
———————————
Active(2)
bla bla
bla bla
Close(1)
bla bla
Can you please point me to right direction ?
Rishi
hi sameer,
Its working perfectly..
thanks a lot!!!
Hi Sameer,
Can we adjust th vertical scroll bar position to center of the ADG when expanding a row ? Currently , if we are expanding the bottom rows, we need scroll down to see the opened nodes. It would be better if opened nodes automaticaly positioned at center /beginning of the grid view.
Please give your thoughts.
Thanks
Hey Sameer,
I’m having problem in sorting my date column in Advance data grid with “DD-MMM-YYYY” format . It doesn’t give proper sort.
I’m using following code in DateTipFunction of Advance data grid ,
private function formatDate(itemA:Object, itemB:Object):int {
//return dateFormatter.format(item.dob);
return ObjectUtil.dateCompare(DateField.stringToDate(itemA.dob, “DD/MMM/YYYY”), DateField.stringToDate(itemB.dob, “DD/MMM/YYYY”));
}
What’s wrong. I must use European format ( DD-MMM-YYYY ) .
Rishi
Sameer,
I’ve being following up your GroupingCollection2 for sometime and finally with the release of FlashBuilder4 gave it a try. I have a very strange effect with wrong calculations in GroupingCollection2. When the same code is applied to the old GroupingCollection the sums are correct? I might be doing something wrong. Please help:
Here is the code:
import mx.collections.ArrayCollection;
import mx.collections.Grouping;
import mx.collections.GroupingCollection;
import mx.collections.GroupingCollection2;
import mx.collections.GroupingField;
import mx.collections.SummaryField;
import mx.collections.SummaryField2;
import mx.collections.SummaryRow;
import mx.controls.advancedDataGridClasses.AdvancedDataGridColumn;
[Bindable]
public var myComponentAC:ArrayCollection = new ArrayCollection([
{product:"Procuct 2 ", description:"Description 2 " , abcd:"abcd1", efgh:"Yes", price:"2 " },
{product:"Procuct 3 " ,description:"Description 2 ", abcd:"abcd2" ,efgh:"Yes" ,price:"3 "},
{ product:"Procuct 4 " ,description:"Description 4 " , abcd:"abcd2", efgh:"Yes", price:"4 " },
{product:"Procuct 5 " ,description:"Description 5 " , abcd:"abcd3" ,efgh:"no" ,price:"5 " },
{product:"Procuct 6 " ,description:"Description 7 " , abcd:"abcd3" ,efgh:"no", price:"6 " },
{product:"Procuct 7 " ,description:"Description 7 " , abcd:"abcd4" ,efgh:"no" ,price:"7 " } ]);
public var gp:GroupingCollection = new GroupingCollection();
protected function groupMe():void{
gp.source = myComponentAC;
// add grouping and label
var group:Grouping = new Grouping();
group.label = “Group”;
// add grouping field & summary for a particular field
var groupField1:GroupingField = new GroupingField(“efgh”);
var groupField2:GroupingField = new GroupingField(“abcd”);
var groupField3:GroupingField = new GroupingField(“description”);
var summRow:SummaryRow = new SummaryRow();
var summField:SummaryField = new SummaryField(“product”, “COUNT”);
var summField2:SummaryField = new SummaryField(“price”, “SUM”);
summRow.fields = [summField,summField2];
summRow.summaryPlacement = “group”;
groupField1.summaries = [summRow];
groupField2.summaries = [summRow];
groupField3.summaries = [summRow];
group.fields = [groupField1,groupField2,groupField3];
gp.grouping = group;
gp.refresh();
myADG.dataProvider = gp;
myADG.validateNow();
myADG.expandAll();
}
public var gp2:GroupingCollection2 = new GroupingCollection2();
protected function groupMe2():void{
gp2.source = myComponentAC;
// add grouping and label
var group:Grouping = new Grouping();
group.label = “Group”;
// add grouping field & summary for a particular field
var groupField1:GroupingField = new GroupingField(“efgh”);
var groupField2:GroupingField = new GroupingField(“abcd”);
var groupField3:GroupingField = new GroupingField(“description”);
var summRow:SummaryRow = new SummaryRow();
var summField:SummaryField2 = new SummaryField2(“product”, “COUNT”);
var summField2:SummaryField2 = new SummaryField2(“price”, “SUM”);
summRow.fields = [summField,summField2];
summRow.summaryPlacement = “group”;
groupField1.summaries = [summRow];
groupField2.summaries = [summRow];
groupField3.summaries = [summRow];
group.fields = [groupField1,groupField2,groupField3];
gp2.grouping = group;
gp2.refresh();
myADG.dataProvider = gp2;
myADG.validateNow();
myADG.expandAll();
}
protected function ungroupMe():void{
myADG.dataProvider = myComponentAC;
}
Trying to paste mxml:
Ok modified MXML for the previous post:
VBox width=”100%” height=”100%”
AdvancedDataGrid id= “myADG” dataProvider=”{myComponentAC}” width=”100%” height=”100%”
columns
AdvancedDataGridColumn dataField=”efgh” headerText=”EFGH”
AdvancedDataGridColumn dataField=”product” headerText=”Product COUNT”
AdvancedDataGridColumn dataField=”price” headerText=”Price SUM”
columns
AdvancedDataGrid
Button click=”groupMe()” label=”GroupingCollection”
Button click=”groupMe2()” label=”GroupingCollection2″
Button click=”ungroupMe()” label=”Grouping refresh”
VBox>
And yes thank you it does work faster !
…and here is little something that worked for me if anybody is interested:
public var gp2:GroupingCollection2 = new GroupingCollection2();
protected function groupMe2():void{
gp2.source = myComponentAC;
// add grouping and label
var group:Grouping = new Grouping();
group.label = “Group”;
// add grouping field & summary for a particular field
var groupField1:GroupingField = new GroupingField(“efgh”);
groupField1.summaries = [SumRow()];
var groupField2:GroupingField = new GroupingField(“abcd”);
groupField2.summaries = [SumRow()];
var groupField3:GroupingField = new GroupingField(“description”);
groupField3.summaries = [SumRow()];
group.fields = [groupField1,groupField2,groupField3];
gp2.grouping = group;
gp2.refresh();
gp2.refresh();
myADG.dataProvider = gp2;
myADG.validateNow();
myADG.expandAll();
}
private function SumRow():SummaryRow {
var SumFieldArr:Array = new Array();
//for ( … ){
SumFieldArr.push(new SummaryField2(“product”, “COUNT”));
SumFieldArr.push(new SummaryField2(“price”, “SUM”));
//}
var newSumRow:SummaryRow = new SummaryRow();
newSumRow.fields = SumFieldArr;
newSumRow.summaryPlacement = “group”;
return newSumRow;
}
Hi Sameer,
Once items are grouped,How can I allow users to even expand n collapse category by clicking the item, For now they must click on “arrow icon” to expand n collapse.
Thanks,
Rishi
Hi Sameer,
I have a performance problem with ADG. I have a report of around 50K rows and it takes 3-4 minutes to render everytime. All the columns in the grid are String type. I know Numerical column grouping takes little time but I have hav string columns.
I see slight difference when I use GroupingCollection2, SummaryField2, but it is also taking around 3 minutes which is not acceptable.
Could you help me out.
Regards,
GK
Hi,
Please help me ,I have an issue with the count and the filterfunction using adg.I need to filter the repeatitions in Territory,show the correct count.Eg:Territory
a,a,b,b.c.It should show the value as a
b,c and the count should be 5.When I use the filter function I get the count as 3.
public class Extendedgrid extends AdvancedDataGrid
{
override public function set dataProvider(value:Object):void
{ // super.dataProvider=value;
super.dataProvider= groupFn(value);
//Alert.show(“value==>”+groupFn(value));
}
[Bindable]
public var myGroup:GroupingCollection;
[Bindable]
public var grouping1:Grouping ;
[Bindable]
var sumRow:SummaryRow;
[Bindable]
var grpfield:GroupingField;
[Bindable]
var sumField1:SummaryField;
[Bindable]
public var tmpAC:ArrayCollection;
public function groupFn(val:Object):GroupingCollection {
myGroup=new GroupingCollection();
grouping1= new Grouping();
sumRow= new SummaryRow();
sumField1=new SummaryField(“Territory”,”COUNT”)
tmpAC = val as ArrayCollection;
tmpAC.filterFunction = deDupe;
myGroup.source=tmpAC;
grpfield=new GroupingField(“Region”);
sumRow.summaryPlacement=”group”;
//sumField1=new SummaryField(“Region”,”COUNT”)
sumField1.label=”COUNT”;
sumRow.fields=[sumField1];
grpfield.summaries=[sumRow];
grouping1.fields= [grpfield];
myGroup.grouping=grouping1;
myGroup.refresh();
// this.invalidateList();
return myGroup;
}
[Bindable]
public var tempObj:Object = {};
/* [Bindable]
public static var Count:int=0 ;
*/
public function deDupe(item:Object):Boolean {
var retVal:Boolean = false;
if (!tempObj.hasOwnProperty(item.Territory)) {
mx.controls.Alert.show(“groupFn”)
tempObj[item.Territory] = item;
retVal = true ;
//Count=Count+1;
} /* lse if(retVal == true ) {
Count=Count+1;
} */
// mx.controls.Alert.show(“Count”+Count);
return retVal;
}
}
}
I have done .Not working.Attaching the full code.Please help me.
————————————–
Extendedgrid
—————————————
package
{
import mx.collections.ArrayCollection;
import mx.collections.Grouping;
import mx.collections.GroupingCollection;
import mx.collections.GroupingField;
import mx.collections.SummaryField;
import mx.collections.SummaryRow;
import mx.controls.AdvancedDataGrid;
import mx.controls.Alert;
public class Extendedgrid extends AdvancedDataGrid
{
override public function set dataProvider(value:Object):void
{ super.dataProvider=groupFn(value);
}
[Bindable]
public var myGroup:GroupingCollection;
[Bindable]
public var grouping1:Grouping ;
public var grid:sampleNewGrid;
[Bindable]
var sumRow:SummaryRow;
[Bindable]
var grpfield:GroupingField;
[Bindable]
var sumField1:SummaryField;
[Bindable]
public var tmpAC:ArrayCollection;
public function groupFn(val:Object):GroupingCollection {
myGroup=new GroupingCollection();
grouping1= new Grouping();
sumRow= new SummaryRow();
sumField1=new SummaryField(“Territory”,”COUNT”);
myGroup.source=val as ArrayCollection;
grpfield=new GroupingField(“Region”);
sumRow.summaryPlacement=”group”;
//sumField1=new SummaryField(“Region”,”COUNT”)
sumField1.label=”COUNT”;
sumRow.fields=[sumField1];
grpfield.summaries=[sumRow];
grouping1.fields= [grpfield];
myGroup.grouping=grouping1;
myGroup.refresh();
tmpAC = val as ArrayCollection;
//tmpAC=myGroup as ArrayCollection;
tmpAC.filterFunction = deDupe;
return myGroup;
}
public var tempObj:Object = {};
public function deDupe(item:Object):Boolean {
var retVal:Boolean = false;
if (!tempObj.hasOwnProperty(item.Territory)) {
tempObj[item.Territory] = item;
retVal = true ;
}
return retVal;
}
}
}
—————————
ExtendedGridColumn
——————————-
package
{
import mx.controls.advancedDataGridClasses.AdvancedDataGridColumn;
[Style(name="rowColor", type="uint", format="Color", inherit="yes")]
public class ExtendedGridColumn extends AdvancedDataGridColumn
{
public function ExtendedGridColumn(columnName:String=null)
{
super(columnName);
}
}
}
Main mXML also attaching:
nOT ABLE TO ATTACH MANIN MXML,
SAMEER can i HAVE YOUR MAIL ID?
The above code does not work in that the “Count” remains “5″ after the collection is filtered.
Hi Sameer,
I used GCollection2 and set the everything as in the examples, but never fixed a problem.
The problem is that myTree shows an unknown RootNode, appears like [object Object], my rootnode seems under this unknown node.
I couldn’t find what I’m missing. What do you think about that
Thanks in advance

November 5, 2009 at 1:59 am
Where can we find the release. Couldn’t find anything in Adobe SVN.
Thanks
November 5, 2009 at 11:57 am
You can download Flash Builder 4 beta 2 release from http://labs.adobe.com/technologies/flashbuilder4/. This beta release contains the data visualization components with GroupingCollection2.