Grouping data in Webix components can be obligatory and optional, static and dynamic.
Obligatory grouping
Grouping is a must-have feature for components that present data hierarchically, yet can be populated with non-hierarchical (inline) datasets.
Such components are subject to initial static grouping. Each group features a group header (parent branch) that are opened to show the group members.
When they are fed with hierarchical data, grouping is not necessary. Read more about data types.
Optional grouping
Data can be grouped, if you need to present data united by some criterion.
With these components, you can see only the result of grouping.
Static/Initial grouping
Grouping criteria are set during component init by the $group key of the scheme object. This is necessary for the components with obligatory grouping.
webix.ui({
view:"tree",
scheme:{
$group:"year"
}
});
Related sample: Tree: Plain JSON Data with Client-side Grouping
Dynamic grouping
Grouping is defined by a function applied to the component.
$$("mytree").group("year");
To cancel grouping, use the ungroup method.
$$("mychart").ungroup();
Syntax for the group() method and the $group object property is the same - you need to specify here the grouping criterion as:
A string that points to the property from the initial dataset:
//static mode
var tree = webix.ui({
view:"tree",
scheme:{
$group:"year"
}
});
//dynamic mode
tree.group("title");
The function is applied to a data object and returns the grouping criterion(-a);
scheme:{
$group:function(obj){
return obj.year/* + ..*/;
}
}
Related sample: List: Grouping
An object with properties defining the grouping criterion and the grouping pattern:
//static mode
webix.ui({
view:"chart",
scheme:{
$group:{
by:"year",
map:{/* ... */}
}
}
});
//dynamic mode
grida.group({
by:"year",
map:{/* ... */}
});
If you use only the by property in the group object, it is the same as if you defined a criterion with a data item or a function. Hence, the following definitions are equal:
$group:"year"
$group: function(obj){ return obj.year;}
$group:{ by:"year" }
$group:{
by: function(obj){ return obj.year }
}
The function can be of any complexity:
by: function(obj){ return Math.floor(obj.year/10); }
Related sample: Static Grouping
Grouping functors are used within map and footer that redefine templates.
$group:{
by:"year",
map:{
property(template):['property', functor]
} //or property:[function (obj){...}]
}
Grouping functors:
Learn more about grouping functors.
If you data set contains data items with missing values ("", null, false or undefined) and you are grouping by that value, there are several options for you to follow:
$$("grid").group({
by:"year",
row:"title",
missing:true //do not need to state, this is default
});
$$("grid").group({
by:"year",
row:"title",
missing:false
});
$$("grid").group({
by:"year",
row:"title",
missing:"Other"
});
If the name of the group is the same as the name of the groups that already exist, the records with missing values will be appended to that group.
Related sample: Treetable: Grouping for Missed Items
By default, component items display the object value which is:
For items that display group headers (parent branches), the value is the one defined by the by criterion:
webix.ui({
view:"tree",
scheme:{
$group:{
by:"year" // group header value
}
},
data: [ //default value
{ id:1, value:"The Shawshank Redemption", year:1994,
votes:678790, rating:9.2, rank:1},
{/* ... */}
]
});
Related sample: Tree: Plain JSON Data with Client-side Grouping
If a component has a template that sets other property as the value for its items, you need to define a map to redefine this value during grouping:
webix.ui({
view:"tree",
template:'{common.icon()} {common.folder()}#title#',
scheme:{
$group:{
by:"year",
map:{
title:["year", "any"]
}
}
}
});
Initially, the template allows showing titles only. The map tells that group title is year and makes "year" the value to show.
Each component has its own peculiarities concerning templates in the grouped mode. Study them below.
In addition, you can change the displayed data by defining a function for the "onGroupCreated" event.
For DataTable and TreeTable data templates are set by column IDs, or column templates, or both.
Yet, in the grouped mode, the grids won't show data for those columns the templates of which are not set either by a template function or by a map.
A map can redefine more than one property.
map:{
votes:["votes", "sum"], // "votes" values will be summed up
title:["year"] // title will take year values
}
Related sample: Data Grouping: Aggregate Values
Function templates allow setting different presentation ways for group items and group headers.
The two snippets produce the same result:
template: function(){
if(obj.$group) return /* ... */; //for group headers
return /* ... */ //for group items
}
template: function(){
if (obj.$level==1) return /* ... */; //for group headers
return /* ... */ //for group items
}
A treetable with a defined map:
columns:[
{
id:"title", template:function(obj, common){
if (obj.$group)
return common.treetable(obj, common) + obj.title;
return obj.title;
}
}
],
scheme: {
$group:{
by: "year",
map:{
title:["year"] //year is 'obj.title' for group header
}
}
}
Related sample: Data Grouping: Aggregate Values
A treetable without a map:
columns:[
{
id:"title", template:function(obj, common){
if (obj.$level == 1)
return common.treetable(obj, common) + obj.value;
return obj.title;
}
}
],
scheme:{
$group:"year" //year is obj.value for group header
}
Related sample: Static Grouping
Row template
The row property within the grouping object sets the group header template for the whole row regardless of grid columns.
grida.group({
by:"year",
map:{
"year":["year", "any"],
"votes":["votes", "sum"]
},
row:function(obj, common){
return "Year "+obj.year+", total votes: "+webix.i18n.numberFormat(obj.votes);
}
});
Related sample: Data Aggregation in Custom Format
Group Footer
The group footer displays a common value for all the members of this group, e.g. total sum, max or min value, etc.
Footers are defined in the same way as map and include the chosen property treated with a functor and a template for the footer row.
grida.group({
by:/* ... */,
map:{/* ... */},
footer:{
votes:["votes", "sum"],
row:function(obj, common){
return "<span style='float:right;'>Total: "
+webix.i18n.numberFormat(obj.votes)+"</span>"
}
}
});
Related sample: Dynamic Grouping: Extra Lines
For a grouped chart grouped items and group headers correspond to each of its axes:
For instance, if you need to display sales of each company, you should group all sales values by company while calculating the sum for each company.
webix.ui({
view:"chart",
value:"#sales#", // the default template for Y-axis
scheme:{
$group({
by:"company", // the template for X-axis
map:{
sales:["sales","sum"]
} //Y-axis template now shows the sum of all sales for each year
});
}
});
The first element in the map is a data item property, while the second one is a functor applied to all the values of this property.
GroupList features its own properties:
See the GroupList article for details.
You can group data by several values.
To group Treetable by several columns, call the group() method for one more time and pass the ID of the branch for grouping as the second parameter:
// first grouping
grida.group({
by:function(obj){ return obj.unitName + "-" + obj.tagName },
map:{
value:["unitName"],
tagName:["tagName"],
samples:["samples","sum"]
}
});
//second grouping
grida.group({
by:"tagName",
map:{
value:["tagName"],
unitName:["unitName"],
samples:["samples","sum"]
}
}, 0);
Related sample: Treetable: Multiple Grouping
To group Datatable by several columns, pass true as the second parameter of the group() method:
grida.group({
by:function(obj){ return obj.unitName + "-" + obj.tagName },
map:{
value:["unitName"],
tagName:["tagName"],
samples:["samples","sum"]
}
});
grida.group({
by:"tagName",
map:{
value:["tagName"],
unitName:["unitName"],
samples:["samples","sum"]
}
}, true);
webix.ui({
view:"treetable",
on:{
"data->onGroupCreated":function(id, value, data){
this.item(id).value = "Year "+value;
}
}
});
grida.group({
by:"year" //obj.value = year
});
Related sample: Handling Events while Data Grouping
Back to top