-
Notifications
You must be signed in to change notification settings - Fork 2.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1545 from yayasoft/3.0-subgrid-final
subgrid feature
- Loading branch information
Showing
14 changed files
with
437 additions
and
22 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
@ngdoc overview | ||
@name Tutorial: 306 Expandable grid | ||
@description | ||
|
||
Module 'ui.grid.expandable' adds the subgrid feature to grid. To show the subgrid you need to provide following grid option: | ||
|
||
<pre> | ||
$scope.gridOptions.expandable = { | ||
//This is the template that will be used to render subgrid. | ||
rowExpandableTemplate: 'rowExpandableTemplate.html', | ||
//This will be the height of the subgrid | ||
expandableRowHeight: 140 | ||
} | ||
</pre> | ||
|
||
rowExpandableTemplate will be template for subgrid and expandableRowHeight will be height of the subgrid. The grid api | ||
provided following events and methods fos subGrids: | ||
|
||
<pre> | ||
//rowExpandedStateChanged is fired for each row as its expanded: | ||
gridApi.expandable.on.rowExpandedStateChanged($scope,function(row){ | ||
}); | ||
//Following methods can be used to expand/ collapse all rows of the grid: | ||
gridApi.expandable.expandAllRows(); | ||
gridApi.expandable.collapseAllRows(); | ||
</pre> | ||
|
||
SubGrid nesting can be done upto multiple levels. | ||
|
||
@example | ||
<example module="app"> | ||
<file name="app.js"> | ||
var app = angular.module('app', ['ui.grid', 'ui.grid.expandable']); | ||
|
||
app.controller('MainCtrl', ['$scope', '$http', '$log', function ($scope, $http, $log) { | ||
$scope.gridOptions = {}; | ||
$scope.gridOptions.expandable = { | ||
rowExpandableTemplate: 'rowExpandableTemplate.html', | ||
expandableRowHeight: 150 | ||
} | ||
|
||
$scope.gridOptions.columnDefs = [ | ||
{ name: 'id'}, | ||
{ name: 'name'}, | ||
{ name: 'age'}, | ||
{ name: 'address.city'} | ||
]; | ||
|
||
$http.get('/data/500_complex.json') | ||
.success(function(data) { | ||
for(i = 0; i < data.length; i++){ | ||
data[i].subGridOptions = { | ||
columnDefs: [ {name:"Id", field:"id"},{name:"Name", field:"name"} ], | ||
data: data[i].friends | ||
} | ||
} | ||
$scope.gridOptions.data = data; | ||
}); | ||
|
||
$scope.gridOptions.onRegisterApi = function(gridApi){ | ||
$scope.gridApi = gridApi; | ||
}; | ||
|
||
$scope.expandAllRows = function() { | ||
$scope.gridApi.expandable.expandAllRows(); | ||
} | ||
|
||
$scope.collapseAllRows = function() { | ||
$scope.gridApi.expandable.collapseAllRows(); | ||
} | ||
}]); | ||
</file> | ||
<file name="index.html"> | ||
<div ng-controller="MainCtrl"> | ||
<div class="control-group"> | ||
<input type="button" class="btn btn-small" ng-click="expandAllRows()" value="Expand All"/> | ||
<input type="button" class="btn btn-small" ng-click="collapseAllRows()" value="Collapse All"/> | ||
</div> | ||
<div ui-grid="gridOptions" ui-grid-pinning ui-grid-expandable class="grid"></div> | ||
</div> | ||
</file> | ||
<file name="main.css"> | ||
.grid { | ||
width: 100%; | ||
height: 400px; | ||
} | ||
</file> | ||
<file name="rowExpandableTemplate.html"> | ||
<div ui-grid="row.entity.subGridOptions" style="height:140px;"></div> | ||
</file> | ||
</example> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,172 @@ | ||
(function () { | ||
'use strict'; | ||
|
||
var module = angular.module('ui.grid.expandable', ['ui.grid']); | ||
|
||
module.service('uiGridExpandableService', ['gridUtil', '$log', '$compile', function (gridUtil, $log, $compile) { | ||
var service = { | ||
initializeGrid: function (grid) { | ||
var publicApi = { | ||
events: { | ||
expandable: { | ||
rowExpandedStateChanged: function (scope, row) { | ||
} | ||
} | ||
}, | ||
methods: { | ||
expandable: { | ||
toggleRowExpansion: function (rowEntity) { | ||
var row = grid.getRow(rowEntity); | ||
if (row !== null) { | ||
service.toggleRowExpansion(grid, row); | ||
} | ||
}, | ||
expandAllRows: function() { | ||
service.expandAllRows(grid); | ||
}, | ||
collapseAllRows: function() { | ||
service.collapseAllRows(grid); | ||
} | ||
} | ||
} | ||
}; | ||
grid.api.registerEventsFromObject(publicApi.events); | ||
grid.api.registerMethodsFromObject(publicApi.methods); | ||
}, | ||
toggleRowExpansion: function (grid, row) { | ||
row.isExpanded = !row.isExpanded; | ||
|
||
if (row.isExpanded) { | ||
row.height = row.grid.options.rowHeight + grid.options.expandable.expandableRowHeight; | ||
} | ||
else { | ||
row.height = row.grid.options.rowHeight; | ||
} | ||
|
||
grid.api.expandable.raise.rowExpandedStateChanged(row); | ||
}, | ||
expandAllRows: function(grid, $scope) { | ||
angular.forEach(grid.renderContainers.body.visibleRowCache, function(row) { | ||
if (!row.isExpanded) { | ||
service.toggleRowExpansion(grid, row); | ||
} | ||
}); | ||
grid.refresh(); | ||
}, | ||
collapseAllRows: function(grid) { | ||
angular.forEach(grid.renderContainers.body.visibleRowCache, function(row) { | ||
if (row.isExpanded) { | ||
service.toggleRowExpansion(grid, row); | ||
} | ||
}); | ||
grid.refresh(); | ||
} | ||
}; | ||
return service; | ||
}]); | ||
|
||
module.directive('uiGridExpandable', ['$log', 'uiGridExpandableService', '$templateCache', | ||
function ($log, uiGridExpandableService, $templateCache) { | ||
return { | ||
replace: true, | ||
priority: 0, | ||
require: '^uiGrid', | ||
scope: false, | ||
compile: function () { | ||
return { | ||
pre: function ($scope, $elm, $attrs, uiGridCtrl) { | ||
var expandableRowHeaderColDef = {name: 'expandableButtons', width: 40}; | ||
expandableRowHeaderColDef.cellTemplate = $templateCache.get('ui-grid/expandableRowHeader'); | ||
uiGridCtrl.grid.addRowHeaderColumn(expandableRowHeaderColDef); | ||
uiGridExpandableService.initializeGrid(uiGridCtrl.grid); | ||
}, | ||
post: function ($scope, $elm, $attrs, uiGridCtrl) { | ||
} | ||
}; | ||
} | ||
}; | ||
}]); | ||
|
||
module.directive('uiGridExpandableRow', | ||
['uiGridExpandableService', '$timeout', '$log', '$compile', 'uiGridConstants','gridUtil','$interval', | ||
function (uiGridExpandableService, $timeout, $log, $compile, uiGridConstants, gridUtil, $interval) { | ||
|
||
return { | ||
replace: false, | ||
priority: 0, | ||
scope: false, | ||
|
||
compile: function () { | ||
return { | ||
pre: function ($scope, $elm, $attrs, uiGridCtrl) { | ||
gridUtil.getTemplate($scope.grid.options.expandable.rowExpandableTemplate).then( | ||
function (template) { | ||
var expandedRowElement = $compile(template)($scope); | ||
$elm.append(expandedRowElement); | ||
$scope.row.expandedRendered = true; | ||
}); | ||
}, | ||
|
||
post: function ($scope, $elm, $attrs, uiGridCtrl) { | ||
$scope.$on('$destroy', function() { | ||
$scope.row.expandedRendered = false; | ||
}); | ||
} | ||
}; | ||
} | ||
}; | ||
}]); | ||
|
||
module.directive('uiGridRow', | ||
['$compile', '$log', '$templateCache', | ||
function ($compile, $log, $templateCache) { | ||
return { | ||
priority: -200, | ||
scope: false, | ||
compile: function ($elm, $attrs) { | ||
return { | ||
pre: function ($scope, $elm, $attrs, controllers) { | ||
|
||
$scope.expandableRow = {}; | ||
|
||
$scope.expandableRow.shouldRenderExpand = function () { | ||
var ret = $scope.colContainer.name === 'body' && $scope.row.isExpanded && (!$scope.grid.isScrollingVertically || $scope.row.expandedRendered); | ||
return ret; | ||
}; | ||
|
||
$scope.expandableRow.shouldRenderFiller = function () { | ||
var ret = $scope.row.isExpanded && ( $scope.colContainer.name !== 'body' || ($scope.grid.isScrollingVertically && !$scope.row.expandedRendered)); | ||
return ret; | ||
}; | ||
|
||
}, | ||
post: function ($scope, $elm, $attrs, controllers) { | ||
} | ||
}; | ||
} | ||
}; | ||
}]); | ||
|
||
module.directive('uiGridViewport', | ||
['$compile', '$log', '$templateCache', | ||
function ($compile, $log, $templateCache) { | ||
return { | ||
priority: -200, | ||
scope: false, | ||
compile: function ($elm, $attrs) { | ||
var rowRepeatDiv = angular.element($elm.children().children()[0]); | ||
var expandedRowFillerElement = $templateCache.get('ui-grid/expandableScrollFiller'); | ||
var expandedRowElement = $templateCache.get('ui-grid/expandableRow'); | ||
rowRepeatDiv.append(expandedRowElement); | ||
rowRepeatDiv.append(expandedRowFillerElement); | ||
return { | ||
pre: function ($scope, $elm, $attrs, controllers) { | ||
}, | ||
post: function ($scope, $elm, $attrs, controllers) { | ||
} | ||
}; | ||
} | ||
}; | ||
}]); | ||
|
||
})(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
@import '../../../less/variables'; | ||
|
||
.expandableRow { | ||
.ui-grid-row { | ||
|
||
&:nth-child(odd) .ui-grid-cell { | ||
background-color: @rowColorOdd; | ||
} | ||
|
||
&:nth-child(even) .ui-grid-cell { | ||
background-color: @rowColorEven; | ||
} | ||
|
||
} | ||
|
||
|
||
} | ||
|
||
.uiGridExpandableButtonsCell { | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
<div ui-grid-expandable-row ng-if="expandableRow.shouldRenderExpand()" class="expandableRow" | ||
style="float:left;margin-top: 1px;margin-bottom: 1px;" | ||
ng-style="{width: (grid.renderContainers.body.getCanvasWidth() - grid.verticalScrollbarWidth) | ||
,height: grid.options.expandable.expandableRowHeight}"></div> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
<div class="ui-grid-row-header-cell uiGridExpandableButtonsCell"> | ||
<div class="ui-grid-cell-contents"> | ||
<i ng-class="{'ui-grid-icon-plus-squared':!row.isExpanded, 'ui-grid-icon-minus-squared':row.isExpanded}" | ||
ng-click="grid.api.expandable.toggleRowExpansion(row.entity)"></i> | ||
</div> | ||
</div> |
9 changes: 9 additions & 0 deletions
9
src/features/expandable/templates/expandableScrollFiller.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
<div ng-if="expandableRow.shouldRenderFiller()" | ||
style="float:left;margin-top: 2px;margin-bottom: 2px" | ||
ng-style="{width: (grid.getViewportWidth()) | ||
,height: grid.options.expandable.expandableRowHeight, 'margin-left': grid.options.rowHeader.rowHeaderWidth}" | ||
> | ||
<i class="ui-grid-icon-spin5 ui-grid-animate-spin" ng-style= | ||
"{'margin-top': ( grid.options.expandable.expandableRowHeight/2 - 5), | ||
'margin-left':((grid.getViewportWidth() - grid.options.rowHeader.rowHeaderWidth)/2 - 5)}"> | ||
</i></div> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
describe('ui.grid.expandable', function () { | ||
|
||
var scope, element, timeout; | ||
|
||
beforeEach(module('ui.grid.expandable')); | ||
|
||
beforeEach(inject(function (_$compile_, $rootScope, $timeout, $httpBackend) { | ||
|
||
var $compile = _$compile_; | ||
scope = $rootScope; | ||
timeout = $timeout; | ||
|
||
scope.gridOptions = {}; | ||
scope.gridOptions.data = [ | ||
{ col1: 'col1', col2: 'col2' } | ||
]; | ||
scope.gridOptions.expandable = { | ||
rowExpandableTemplate: 'rowExpandableTemplate.html', | ||
expandableRowHeight: 150 | ||
}; | ||
scope.gridOptions.onRegisterApi = function (gridApi) { | ||
scope.gridApi = gridApi; | ||
scope.grid = gridApi.grid; | ||
}; | ||
|
||
$httpBackend.when('GET', 'rowExpandableTemplate.html').respond("<div class='test'></div>"); | ||
element = angular.element('<div class="col-md-5" ui-grid="gridOptions" ui-grid-expandable></div>'); | ||
|
||
$timeout(function () { | ||
$compile(element)(scope); | ||
}); | ||
$timeout.flush(); | ||
})); | ||
|
||
it('public api expandable should be well defined', function () { | ||
expect(scope.gridApi.expandable).toBeDefined(); | ||
expect(scope.gridApi.expandable.on.rowExpandedStateChanged).toBeDefined(); | ||
expect(scope.gridApi.expandable.raise.rowExpandedStateChanged).toBeDefined(); | ||
expect(scope.gridApi.expandable.toggleRowExpansion).toBeDefined(); | ||
expect(scope.gridApi.expandable.expandAllRows).toBeDefined(); | ||
expect(scope.gridApi.expandable.collapseAllRows).toBeDefined(); | ||
}); | ||
|
||
it('expandAll and collapseAll should set and unset row.isExpanded', function () { | ||
scope.gridApi.expandable.expandAllRows(); | ||
scope.grid.rows.forEach(function(row) { | ||
expect(row.isExpanded).toBe(true); | ||
}); | ||
scope.gridApi.expandable.collapseAllRows(); | ||
scope.grid.rows.forEach(function(row) { | ||
expect(row.isExpanded).toBe(false); | ||
}); | ||
}); | ||
|
||
it('event rowExpandedStateChanged should be fired whenever row expands', function () { | ||
var functionCalled = false; | ||
scope.gridApi.expandable.on.rowExpandedStateChanged(scope,function(row){ | ||
functionCalled = true; | ||
}); | ||
scope.gridApi.expandable.toggleRowExpansion(scope.grid.rows[0].entity); | ||
expect(functionCalled).toBe(true); | ||
}); | ||
|
||
it('subgrid should be addeed to the dom when we expand row', function () { | ||
expect(element.find('.test').length).toBe(0); | ||
scope.gridApi.expandable.toggleRowExpansion(scope.grid.rows[0].entity); | ||
scope.$digest(); | ||
timeout(function () { | ||
expect(element.find('.test').length).toBe(1); | ||
}); | ||
}); | ||
}); |
Oops, something went wrong.