I've tried to achieve the multi column grouping at column header level for UI-Grid with the below approach.
Steps I've followed:
Include the below header cell template, of the UI grid, with another "UI Grid row":
<div class="ui-grid-header custom-ui-grid-header">
<div class="ui-grid-top-panel">
<div class="ui-grid-header-viewport">
<div class="ui-grid-header-canvas">
<div class="ui-grid-header-cell-wrapper" ng-style="colContainer.headerCellWrapperStyle()">
<div class="ui-grid-header-cell-row">
<div class="ui-grid-header-cell" ng-repeat="superCol in grid.options.superColDefs track by $index" col-name="{{superCol.name}}">
<div class="ui-grid-cell-contents" data-ng-bind="superCol.displayName">
</div>
</div>
</div>
<div class="ui-grid-header-cell-row">
<div class="ui-grid-header-cell ui-grid-clearfix" ng-repeat="col in colContainer.renderedColumns track by col.colDef.name" ui-grid-header-cell super-col-width-update col="col" render-index="$index">
</div>
</div>
</div>
</div>
</div>
<div ui-grid-menu></div>
</div>
</div>
Add references to your column definition object of the grid with Super Column data:
$scope.gridOptions = {
headerTemplate: 'views/header-template.html',
superColDefs: [{
name: 'group1',
displayName: 'Group 1'
}, {
name: 'group2',
displayName: 'Group 2'
}],
columnDefs: [{
name: 'name',
displayName: 'Name',
superCol: 'group1'
}, {
name: 'title',
displayName: 'Title',
superCol: 'group1'
}, {
name: 'age',
displayName: 'Age',
superCol: 'group2'
}],
data: [{
name: 'Bob',
title: 'CEO',
age: '31'
}, {
name: 'Frank',
title: 'Lowly Developer',
age: '33'
}]
};
Calculate the width of each header column, and add it to its Super Column's width, to make each relevant Super cell to span across its child cells. This can be achieved with a directive that will be placed on every child header cell.
Directive:
.directive('superColWidthUpdate', ['$timeout', function ($timeout) {
return {
'restrict': 'A',
'link': function (scope, element) {
var _colId = scope.col.colDef.superCol,
_el = jQuery(element);
_el.on('resize', function () {
_updateSuperColWidth();
});
var _updateSuperColWidth = function () {
$timeout(function () {
var _parentCol = jQuery('.ui-grid-header-cell[col-name="' + _colId + '"]');
var _parentWidth = _parentCol.outerWidth(),
_width = _el.outerWidth();
_parentWidth = ((_parentWidth === 1) ? 0 : _parentWidth) + _width + 'px';
_parentCol.css({
'min-width': _parentWidth,
'max-width': _parentWidth
});
}, 0);
};
_updateSuperColWidth();
}
};
}]);
In the above approach, the solution has been achieved by manipulating the DOM to render a new header row and new header cells, which sit on top of the usual header row, but within the Header viewport.
However, I am looking for any better approach, may be by using the UI-Grid's internal services or directives. Any help here is much appreciated!
Multi-column grouping isn't something the grid currently does, one of the barriers is the interaction with column moving and resizing.
Having said that, we'd like to have it, and looking at what you've done I reckon you could help to write that feature in ui-grid.
I'm not entirely sure how column grouping would work with column moving - perhaps it would always force the entire group to move, not just an individual column. With resizing basically the group column needs to have a width that equals the total of the sub columns.
That's basically what you've done already, the only trick is to fit it into the feature structure.
If you want to drop onto the gitter channel sometime https://gitter.im/angular-ui/ng-grid you'd probably find people would give you a hand with that PR (probably @c0bra would be best placed to help)