Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
159 changes: 159 additions & 0 deletions examples/customgroups.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
/*jshint loopfunc: true*/
/*global _, define*/

/** This advanced example shows how groups can be used with more flexibility with the custom grouping feature **/
define([], function () {
"use strict";

// Get the full qualified group name i.e. the subgroup "1" of parent group "A" would get: "A,1" and so on
var getFullGroupValue = function(group){
var parentValue = "";
if(group.parentGroup){
parentValue = getFullGroupValue(group.parentGroup);
}
return parentValue ? parentValue + "," + group.value : group.value;
};

var groupsLoaded = {};

return [function () {

// Generate Data
var data = [];
for (var i = 0; i < 50; i++) {
data.push({
id: i,
data: {
id: i,
population: _.sample(_.range(15, 100)),
elevation: _.sample(_.range(500, 10000)),
language: _.sample(["English", "French", "Italian", "Latin", null]),
city: ['Venice', 'Vatican City', 'Rome', 'Milan', 'Constantinople'][_.random(0, 4)],
customGroup: ['A', 'B', 'A,2'][_.random(0, 2)],
}
});
}

// Generate Columns
var columns = [{
id: "id",
name: "ID",
field: "id",
sortable: true,
removable: true
}, {
id: "city",
name: "City",
field: "city",
minWidth: 160,
sortable: true,
removable: true
}, {
category: "Statistical",
id: "elevation",
name: "Elevation",
field: "elevation",
minWidth: 100,
sortable: true,
removable: true
}, {
category: "Statistical",
id: "population",
name: "Population",
field: "population",
minWidth: 100,
sortable: true,
removable: true
}, {
category: "Statistical",
id: "language",
name: "Language",
field: "language",
sortable: true,
removable: true
},{
// this column contains the "path" to the group that the item belongs to
id: "customGroup",
name: "customGroup",
field: "customGroup",
visible: false,
sortable: true,
removable: true
}];

return {
columns: columns,
data: data,
keepNullsAtBottom: false,
quickFilter: true,
stickyGroupRows: true
};

}, function (grid) {

// Add two levels of custom grouping, with a custom getter and formatter function
grid.setCustomGrouping([{
getter: function(r){var p = r.data.customGroup.split(","); if(p[0]) return p[0]; return null},
formatter: function(r, c, v, def, data){
var html = "";
html += data.collapsed ? "+" : "-";
html += " " + data.value;
return html;
},
groupNulls: false,
groups: [{
count: 432,
value: 'A'
}, {
count: 192,
value: 'B'
}]
}, {
getter: function(r){var p = r.data.customGroup.split(","); if(p[1]) return p[1]; return null},
formatter: function(r, c, v, def, data){
var html = "";
html += data.collapsed ? "+" : "-";
html += " " + data.value;
return html;
},
groupNulls: false,
groups: [{
count: 12,
value: '1',
parent: 'A'
}, {
count: 14,
value: '2',
parent: 'A'
}]
}]);

// When the group header is clicked, load addional items of the group
grid.on("groupheaderclick", function(event, options){
var item = options.item;
var data = [];
if(item.level < 1) return;

// This could be an ajax call or other asynchronous calls
setTimeout(function(){
var fullValue = getFullGroupValue(item);
if(groupsLoaded[fullValue]) return;
for (var i = 0; i < 25; i++) {
data.push({
id: "new_" + item.value + "_" + i,
data: {
id: "new_" + item.value + "_" + i,
population: _.sample(_.range(15, 100)),
elevation: _.sample(_.range(500, 10000)),
language: _.sample(["English", "French", "Italian", "Latin", null]),
city: ['Venice', 'Vatican City', 'Rome', 'Milan', 'Constantinople'][_.random(0, 4)],
customGroup: fullValue,
}
});
}
grid.add(data);
groupsLoaded[fullValue] = true;
}, 500);
});
}];
});
1 change: 1 addition & 0 deletions examples/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,7 @@
<li><a href="#autoheight">Automatic Height</a></li>
<li><a href="#rowselect">Row Selection</a></li>
<li><a href="#frozencolumns">Frozen Columns</a></li>
<li><a href="#customgroups">Custom Groups</a></li>
<li><a href="#menuextensions">Menu Extensions</a></li>
</ul>

Expand Down
78 changes: 68 additions & 10 deletions src/doby-grid.js
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,7 @@ var DobyGrid = function (options) {
handleKeyDown,
handleScroll,
handleWindowResize,
hasCustomGrouping = false,
hasFrozenRows = false,
hasGrouping,
hasSorting,
Expand Down Expand Up @@ -560,6 +561,12 @@ var DobyGrid = function (options) {
// Use the column_id shortcut to extend the options
options.column_id = column_id;

if (hasCustomGrouping) {
// Disable custom grouping
hasCustomGrouping = false;
this.collection.groups = [];
}

// Add to grouping
this.collection.groups.push(options);

Expand Down Expand Up @@ -1843,16 +1850,15 @@ var DobyGrid = function (options) {
*
* @returns {object}
*/
createGroupingObject = function (grouping) {
createGroupingObject = function (grouping, custom) {
if (!grouping) throw new Error("Unable to create group because grouping object is missing.");

if (grouping.column_id === undefined) throw new Error("Unable to create grouping object because 'column_id' is missing.");
if (!custom && grouping.column_id === undefined) throw new Error("Unable to create grouping object because 'column_id' is missing.");

var column = getColumnById(grouping.column_id);

var result = $.extend({
collapsed: true, // All groups start off being collapsed
column_id: column.id,
comparator: function (a, b) {
// Null groups always on the bottom
if (self.options.keepNullsAtBottom) {
Expand All @@ -1872,12 +1878,16 @@ var DobyGrid = function (options) {
var sorted = naturalSort(a.value, b.value);
return asc ? sorted : -sorted;
},
getter: function (item) {
getter: !custom && function (item) {
return getDataItemValueForColumn(item, column);
},
rows: []
}, grouping);

if (!custom) {
result.column_id = column.id;
}

return result;
};

Expand Down Expand Up @@ -1957,7 +1967,7 @@ var DobyGrid = function (options) {

// If we have normal data - set it now
if (!grid.fetcher && grid.options.data) {
this.reset(grid.options.data);
self.reset(grid.options.data);
}

return this;
Expand Down Expand Up @@ -2298,6 +2308,22 @@ var DobyGrid = function (options) {
}
}

// If we have custom grouping, just add the groups provided
if (hasCustomGrouping) {
var cm_g;
for (var o = 0, clength = self.groups[level].groups.length; o < clength; o++) {
cm_g = self.groups[level].groups[o];

// For each parent, walk up the hierarchy of group parents and
// confirm that this sub-group belongs there
if (!checkRemoteGroup(level, cm_g, parentGroup)) continue;

group = createGroupObject(cm_g);
groups.push(group);
groupsByVal[group.value] = group;
}
}

// Loop through the rows in the group and create group header rows as needed
for (i = 0, l = rows.length; i < l; i++) {
r = rows[i];
Expand Down Expand Up @@ -2925,7 +2951,7 @@ var DobyGrid = function (options) {
// Do not create groups when the grid is empty.
//
var groups = [];
if (self.groups.length && self.items.length) {
if (self.groups.length && (self.items.length || hasCustomGrouping)) {

extractGroups(newRows, null, function (result) {
groups = result;
Expand Down Expand Up @@ -3086,7 +3112,7 @@ var DobyGrid = function (options) {
* @param {array} options - List of grouping objects
*
*/
this.setGrouping = function (options) {
this.setGrouping = function (options, custom) {
// Is grouping enabled
if (!grid.options.groupable) throw new Error('Cannot execute "setGrouping" because "options.groupable" is disabled.');

Expand All @@ -3111,12 +3137,19 @@ var DobyGrid = function (options) {

col = getColumnById(options[i].column_id);

if (col === undefined) {
// Don't care for a column id, if we're setting a custom grouping
if (!custom && col === undefined) {
throw new Error('Cannot add grouping for column "' + options[i].column_id + '" because no such column could be found.');
} else if (col.groupable === false) {
} else if (!custom && col.groupable === false) {
throw new Error('Cannot add grouping for column "' + col.id + '" because "options.groupable" is disabled for that column.');
}

if (custom && !options[i].getter) {
throw new Error('Cannot add custom grouping: a getter function must be provided for each grouping option');
} else if (custom && !options[i].formatter) {
throw new Error('Cannot add custom grouping: a formatter function must be provided for each grouping option');
}

// If there are custom heights set for groupings - enable variable row height
if (!variableRowHeight && (
(options[i].height !== undefined && options[i].height !== null) ||
Expand All @@ -3128,7 +3161,7 @@ var DobyGrid = function (options) {
if (!toggledGroupsByLevel[i]) toggledGroupsByLevel[i] = {};

// Extend using a default grouping object and add to groups
groups.push(createGroupingObject(options[i]));
groups.push(createGroupingObject(options[i], custom));
}

// Consider groupings changed if the number of groupings changed
Expand Down Expand Up @@ -5512,6 +5545,10 @@ var DobyGrid = function (options) {
var isToggler = $(e.target).hasClass(CLS.grouptoggle) || $(e.target).closest('.' + CLS.grouptoggle).length;

if (isToggler) {
self.trigger('groupheaderclick', e, {
item: item
});

if (item.collapsed) {
self.collection.expandGroup(item[self.options.idProperty]);
} else {
Expand Down Expand Up @@ -8675,6 +8712,26 @@ var DobyGrid = function (options) {
}
};

/**
* Sets a custom grouping for the grid data view.
* @method setCustomGrouping
* @memberof DobyGrid
*
* @param {array} options - List of grouping objects
*
* @returns {object}
*/
this.setCustomGrouping = function (options) {

if (!options || !options.length) {
throw new Error('There must be at least one grouping option to set custom grouping');
}

hasCustomGrouping = true;
this.collection.setGrouping(options, true);

return this;
};

/**
* Validates and sets up options for frozen columns and rows
Expand Down Expand Up @@ -8713,6 +8770,7 @@ var DobyGrid = function (options) {
* @returns {object}
*/
this.setGrouping = function (options) {
hasCustomGrouping = false;
this.collection.setGrouping(options);
return this;
};
Expand Down