diff --git a/packages/oui-datagrid/README.md b/packages/oui-datagrid/README.md index a4efa896..d1fe6b50 100644 --- a/packages/oui-datagrid/README.md +++ b/packages/oui-datagrid/README.md @@ -91,6 +91,38 @@ Clicked row action 1: {{$ctrl.action1Row.lastName}}, {{$ctrl.action1Row.firstName}} ``` +### Selectable rows + +```html:preview + + + + + {{$row.parents.mother.lastName}}, {{$row.parents.mother.firstName}} + + + {{$row.parents.father.lastName}}, {{$row.parents.father.firstName}} + + + {{$ctrl.label}}: {{$value}} + + + + {{$value|date:short}} + + + {{ $isSelected }} + + + + + + +
You have selected {{ $selectedRows.length }} row(s).
+
+
+``` + ### Empty datagrid ```html:preview @@ -656,6 +688,7 @@ call `rows-loader` and then a `row-loader` call for each line. | `rows-loader` | function | &? | yes | | | gets all rows (returns a promise with all rows) | | `row-loader` | function | &? | yes | | | gets row details (returns a promise with details) | | `customizable` | boolean | this.datagridCtrl.selectedRows[this.index], (isSelected) => { + this.cellScope.$isSelected = isSelected || false; + }); } $onChanges (changes) { diff --git a/packages/oui-datagrid/src/datagrid.controller.js b/packages/oui-datagrid/src/datagrid.controller.js index 024c1b2d..4d1dde80 100644 --- a/packages/oui-datagrid/src/datagrid.controller.js +++ b/packages/oui-datagrid/src/datagrid.controller.js @@ -35,6 +35,8 @@ export default class DatagridController { this.columnElements = []; this.actionColumnElements = []; this.extraTopElements = []; + this.selectedRows = []; + this.selectAllRows = false; this.config = ouiDatagridConfiguration; @@ -69,6 +71,8 @@ export default class DatagridController { this.filterableColumns = []; this.criteria = []; + addBooleanParameter(this, "selectableRows"); + if (this.id) { this.ouiDatagridService.registerDatagrid(this); } @@ -103,7 +107,7 @@ export default class DatagridController { } // Manage responsiveness - if (this.hasActionMenu || this.customizable) { + if (this.hasActionMenu || this.customizable || this.selectableRows) { this.scrollablePanel = this.$element[0].querySelector(".oui-datagrid-responsive-container__overflow-container"); if (this.scrollablePanel) { angular.element(this.$window).on("resize", this.checkScroll); @@ -271,6 +275,9 @@ export default class DatagridController { this.displayedRows = DatagridController.createEmptyRows(this.paging.getCurrentPageSize()); } + this.selectedRows = this.selectedRows.map(() => false); + this.selectAllRows = false; + this.refreshDatagridPromise = this.$q.when((callback || angular.noop)()) .then(() => this.paging.loadData(skipSortAndFilter, forceLoadRows)) .then(result => { @@ -313,6 +320,37 @@ export default class DatagridController { }; } + getSelectedRows () { + return this.selectedRows.reduce((result, isSelected, index) => { + if (isSelected) { + result.push(this.displayedRows[index]); + } + return result; + }, []); + } + + toggleRowSelection (index, isSelected) { + const rowCount = this.displayedRows.length; + this.selectedRows[index] = isSelected; + const selectedRowsCount = this.getSelectedRows().length; + + if (selectedRowsCount === rowCount) { + this.selectAllRows = true; + } else if (selectedRowsCount === 0) { + this.selectAllRows = false; + } else { + this.selectAllRows = null; + } + } + + toggleAllRowsSelection (modelValue) { + if (modelValue === null) { + this.selectedRows = this.displayedRows.map(() => true); + } else { + this.selectedRows = this.displayedRows.map(() => modelValue); + } + } + static createEmptyRows (pageSize) { return Array(...{ length: pageSize }) .map(() => undefined); diff --git a/packages/oui-datagrid/src/datagrid.html b/packages/oui-datagrid/src/datagrid.html index 807c41ff..ea03452a 100644 --- a/packages/oui-datagrid/src/datagrid.html +++ b/packages/oui-datagrid/src/datagrid.html @@ -18,18 +18,25 @@ items="$ctrl.appliedCriteria">
+ + ng-repeat="row in $ctrl.displayedRows track by $index" + ng-init="rowIndex = $index"> + diff --git a/packages/oui-datagrid/src/extra-top/extra-top.component.js b/packages/oui-datagrid/src/extra-top/extra-top.component.js index 94100dc2..6adab478 100644 --- a/packages/oui-datagrid/src/extra-top/extra-top.component.js +++ b/packages/oui-datagrid/src/extra-top/extra-top.component.js @@ -4,5 +4,8 @@ export default { controller, require: { datagridCtrl: "^^ouiDatagrid" + }, + bindings: { + selectedItems: "<" } }; diff --git a/packages/oui-datagrid/src/extra-top/extra-top.controller.js b/packages/oui-datagrid/src/extra-top/extra-top.controller.js index 51809cc1..09eb4813 100644 --- a/packages/oui-datagrid/src/extra-top/extra-top.controller.js +++ b/packages/oui-datagrid/src/extra-top/extra-top.controller.js @@ -7,6 +7,10 @@ export default class { $postLink () { this.extraTopScope = this.datagridCtrl.getParentScope().$new(false); + this.extraTopScope.$selectedRows = []; + this.extraTopScope.$watchCollection(() => this.datagridCtrl.getSelectedRows(), (rows) => { + this.extraTopScope.$selectedRows = rows || []; + }); this._compileElement(); } diff --git a/packages/oui-datagrid/src/index.spec.js b/packages/oui-datagrid/src/index.spec.js index 51a9dfed..0af9c61f 100644 --- a/packages/oui-datagrid/src/index.spec.js +++ b/packages/oui-datagrid/src/index.spec.js @@ -417,6 +417,94 @@ describe("ouiDatagrid", () => { }); }); + describe("Selectable rows", () => { + + it("should toggle row selection", () => { + const element = TestUtils.compileTemplate(` + + + + `, { + rows: fakeData.slice(0, 5) + }); + const ctrl = element.controller("ouiDatagrid"); + + let selection = []; + ctrl.toggleRowSelection(0, true); + selection = ctrl.getSelectedRows(); + expect(selection.length).toBe(1); + expect(selection[0]).toEqual(fakeData[0]); + + ctrl.toggleRowSelection(0, false); + selection = ctrl.getSelectedRows(); + expect(selection.length).toBe(0); + }); + + it("should toggle all rows", () => { + const element = TestUtils.compileTemplate(` + + + + `, { + rows: fakeData.slice(0, 5) + }); + const ctrl = element.controller("ouiDatagrid"); + + let selection = []; + expect(ctrl.selectAllRows).toBe(false); + ctrl.toggleAllRowsSelection(true); + selection = ctrl.getSelectedRows(); + expect(selection.length).toBe(5); + + ctrl.toggleAllRowsSelection(false); + selection = ctrl.getSelectedRows(); + expect(selection.length).toBe(0); + }); + + it("should update global selection checkbox", () => { + const element = TestUtils.compileTemplate(` + + + + `, { + rows: fakeData.slice(0, 5) + }); + const ctrl = element.controller("ouiDatagrid"); + + expect(ctrl.selectAllRows).toBe(false); + ctrl.toggleRowSelection(0, true); + expect(ctrl.selectAllRows).toBe(null); + ctrl.toggleRowSelection(1, true); + ctrl.toggleRowSelection(2, true); + ctrl.toggleRowSelection(3, true); + expect(ctrl.selectAllRows).toBe(null); + ctrl.toggleRowSelection(4, true); + expect(ctrl.selectAllRows).toBe(true); + ctrl.toggleRowSelection(4, false); + expect(ctrl.selectAllRows).toBe(null); + ctrl.toggleRowSelection(0, false); + ctrl.toggleRowSelection(1, false); + ctrl.toggleRowSelection(2, false); + ctrl.toggleRowSelection(3, false); + expect(ctrl.selectAllRows).toBe(false); + }); + + it("should updates extra-top content", () => { + const element = TestUtils.compileTemplate(` + + + + {{ $selectedRows.length }} + `, { + rows: fakeData.slice(0, 5) + }); + const ctrl = element.controller("ouiDatagrid"); + ctrl.toggleAllRowsSelection(true); + element.scope().$apply(); + expect(element.find("oui-datagrid-extra-top").text()).toBe("5"); + }); + }); + describe("Remote rows", () => { let rowsLoaderSpy;
+ + +
+ + + + column="column" + index="rowIndex"> + column="$ctrl.actionColumn" + index="rowIndex">