diff --git a/packages/core/src/js/factories/Grid.js b/packages/core/src/js/factories/Grid.js index fe038e654..6e7a1026c 100644 --- a/packages/core/src/js/factories/Grid.js +++ b/packages/core/src/js/factories/Grid.js @@ -1106,6 +1106,65 @@ angular.module('ui.grid') }); }; + /** + * @ngdoc function + * @name getRowsByKey + * @methodOf ui.grid.class:Grid + * @description returns the GridRows who have an key that is equal to comparator + * @param {boolean} isInEntity if true then key is in entity else it's directly in row + * @param {(string|number)} key the key to look for + * @param {any} comparator the value that key should have + * @param {array} lookInRows [optional] the rows to look in - if not provided then + * looks in grid.rows + */ + Grid.prototype.getRowsByKey = function getRowsByKey(isInEntity, key, comparator, lookInRows) { + if ( key == void 0 ) { + return null; + } + + lookInRows = lookInRows == void 0 ? this.rows : lookInRows; + var func = isInEntity ? function (row) { + return row.entity != void 0 && row.entity.hasOwnProperty(key) && row.entity[key] === comparator; + } : function (row) { + return row.hasOwnProperty(key) && row[key] === comparator; + } + + return lookInRows.filter(func); + }; + + /** + * @ngdoc function + * @name findRowByKey + * @methodOf ui.grid.class:Grid + * @description returns the first GridRow which has an key that is equal to comparator + * @param {boolean} isInEntity if true then key is in entity else it's directly in row + * @param {(string|number)} key the key to look for + * @param {any} comparator the value that key should have + * @param {array} lookInRows [optional] the rows to look in - if not provided then + * looks in grid.rows + */ + Grid.prototype.findRowByKey = function findRowByKey(isInEntity, key, comparator, lookInRows) { + var result = null; + if ( key != void 0 ) { + lookInRows = lookInRows == void 0 ? this.rows : lookInRows; + var func = isInEntity ? function (row) { + if ( row.entity != void 0 && row.entity.hasOwnProperty(key) && row.entity[key] === comparator ) { + result = row; + return false; + } + return true; + } : function (row) { + if ( row.hasOwnProperty(key) && row[key] === comparator ) { + result = row; + return false; + } + return true; + } + + lookInRows.every(func); + } + return result + }; /** * @ngdoc function diff --git a/packages/core/test/core/factories/Grid.spec.js b/packages/core/test/core/factories/Grid.spec.js index 690a78a4e..31ad34096 100644 --- a/packages/core/test/core/factories/Grid.spec.js +++ b/packages/core/test/core/factories/Grid.spec.js @@ -324,6 +324,64 @@ describe('Grid factory', function() { }); }); + describe('getting Rows', function() { + it('should get Rows', function() { + expect(grid.getRow()).toBe(null); + expect(grid.getRow(grid.rows[0].entity)).toBe(grid.rows[0]); + expect(grid.getRow(grid.rows[0].entity), [grid.rows[0]]).toBe(grid.rows[0]); + }); + + it('should get Rows by key', function() { + grid.rows[0].entity = {str: 'abc', num: 123, nll: null, multi: true}; + grid.rows[1].entity = {multi: true}; + grid.rows[0].str = 'abc'; + grid.rows[0].num = 123; + grid.rows[0].nll = null; + grid.rows[0].innerMulti = false; + grid.rows[1].innerMulti = false; + + expect(grid.getRowsByKey()).toBe(null); + expect(grid.getRowsByKey(true, "test")).toEqual([]); + expect(grid.getRowsByKey(true, "str", "abc")[0].entity).toBe(grid.rows[0].entity); + expect(grid.getRowsByKey(true, "str", "def")).toEqual([]); + expect(grid.getRowsByKey(true, "num", 123)[0].entity).toBe(grid.rows[0].entity); + expect(grid.getRowsByKey(true, "nll", null)[0].entity).toBe(grid.rows[0].entity); + expect(grid.getRowsByKey(true, "multi", true).length).toBe(2); + + expect(grid.getRowsByKey(false, "test")).toEqual([]); + expect(grid.getRowsByKey(false, "str", "abc")).toEqual([grid.rows[0]]); + expect(grid.getRowsByKey(false, "str", "def")).toEqual([]); + expect(grid.getRowsByKey(false, "num", 123)).toEqual([grid.rows[0]]); + expect(grid.getRowsByKey(false, "nll", null)).toEqual([grid.rows[0]]); + expect(grid.getRowsByKey(false, "innerMulti", false).length).toBe(2); + }); + + it('should find first Row by key', function() { + grid.rows[0].entity = {str: 'abc', num: 123, nll: null, multi: true}; + grid.rows[1].entity = {multi: true}; + grid.rows[0].str = 'abc'; + grid.rows[0].num = 123; + grid.rows[0].nll = null; + grid.rows[0].innerMulti = false; + grid.rows[1].innerMulti = false; + + expect(grid.findRowByKey()).toBe(null); + expect(grid.findRowByKey(true, "test")).toBe(null); + expect(grid.findRowByKey(true, "str", "abc").entity).toBe(grid.rows[0].entity); + expect(grid.findRowByKey(true, "str", "def")).toBe(null); + expect(grid.findRowByKey(true, "num", 123).entity).toBe(grid.rows[0].entity); + expect(grid.findRowByKey(true, "nll", null).entity).toBe(grid.rows[0].entity); + expect(grid.findRowByKey(true, "multi", true).entity).toBe(grid.rows[0].entity); + + expect(grid.findRowByKey(false, "test")).toBe(null); + expect(grid.findRowByKey(false, "str", "abc")).toBe(grid.rows[0]); + expect(grid.findRowByKey(false, "str", "def")).toBe(null); + expect(grid.findRowByKey(false, "num", 123)).toBe(grid.rows[0]); + expect(grid.findRowByKey(false, "nll", null)).toBe(grid.rows[0]); + expect(grid.findRowByKey(false, "innerMulti", false).entity).toBe(grid.rows[0].entity); + }); + }) + describe('buildColumns', function() { it('guess correct column types when not specified', function() { var dataRow = {str: 'abc', num: 123, dat: new Date(), bool: true, obj: {}, nll: null, negNum: -1, posNum: +1}; diff --git a/packages/selection/src/js/selection.js b/packages/selection/src/js/selection.js index 7d0898869..48901c6ac 100644 --- a/packages/selection/src/js/selection.js +++ b/packages/selection/src/js/selection.js @@ -201,7 +201,7 @@ */ toggleRowSelection: function (rowEntity, evt) { var row = grid.getRow(rowEntity); - if (row !== null) { + if (row != void 0 && row !== null) { service.toggleRowSelection(grid, row, evt, grid.options.multiSelect, grid.options.noUnselect, true); } }, @@ -215,7 +215,7 @@ */ selectRow: function (rowEntity, evt) { var row = grid.getRow(rowEntity); - if (row !== null && !row.isSelected) { + if (row != void 0 && row !== null && !row.isSelected) { service.toggleRowSelection(grid, row, evt, grid.options.multiSelect, grid.options.noUnselect, true); } }, @@ -232,7 +232,24 @@ */ selectRowByVisibleIndex: function (rowNum, evt) { var row = grid.renderContainers.body.visibleRowCache[rowNum]; - if (row !== null && typeof (row) !== 'undefined' && !row.isSelected) { + if (row != void 0 && row !== null && typeof (row) !== 'undefined' && !row.isSelected) { + service.toggleRowSelection(grid, row, evt, grid.options.multiSelect, grid.options.noUnselect, false); + } + }, + /** + * @ngdoc function + * @name selectRowByKey + * @methodOf ui.grid.selection.api:PublicApi + * @description Select the data row + * @param {boolean} isInEntity if true then key is in entity else it's directly in row + * @param {Symbol} key the key to look for + * @param {any} comparator the value that key should have + * @param {Event} evt object if raised from an event + * @param {array} lookInRows [optional] the rows to look in - if not provided then looks in grid.rows + */ + selectRowByKey: function (isInEntity, key, comparator, evt, lookInRows) { + var row = grid.findRowByKey(isInEntity, key, comparator, lookInRows); + if (row != void 0 && row !== null && typeof (row) !== 'undefined' && !row.isSelected) { service.toggleRowSelection(grid, row, evt, grid.options.multiSelect, grid.options.noUnselect, false); } }, @@ -246,7 +263,7 @@ */ unSelectRow: function (rowEntity, evt) { var row = grid.getRow(rowEntity); - if (row !== null && row.isSelected) { + if (row != void 0 && row !== null && row.isSelected) { service.toggleRowSelection(grid, row, evt, grid.options.multiSelect, grid.options.noUnselect, true); } }, @@ -263,7 +280,24 @@ */ unSelectRowByVisibleIndex: function (rowNum, evt) { var row = grid.renderContainers.body.visibleRowCache[rowNum]; - if (row !== null && typeof (row) !== 'undefined' && row.isSelected) { + if (row != void 0 && row !== null && typeof (row) !== 'undefined' && row.isSelected) { + service.toggleRowSelection(grid, row, evt, grid.options.multiSelect, grid.options.noUnselect, false); + } + }, + /** + * @ngdoc function + * @name unSelectRowByKey + * @methodOf ui.grid.selection.api:PublicApi + * @description Select the data row + * @param {boolean} isInEntity if true then key is in entity else it's directly in row + * @param {(string|number)} key the key to look for + * @param {any} comparator the value that key should have + * @param {Event} evt object if raised from an event + * @param {array} lookInRows [optional] the rows to look in - if not provided then looks in grid.rows + */ + unSelectRowByKey: function (isInEntity, key, comparator, evt, lookInRows) { + var row = grid.findRowByKey(isInEntity, key, comparator, lookInRows); + if (row != void 0 && row !== null && typeof (row) !== 'undefined' && row.isSelected) { service.toggleRowSelection(grid, row, evt, grid.options.multiSelect, grid.options.noUnselect, false); } }, diff --git a/packages/selection/test/uiGridSelectionService.spec.js b/packages/selection/test/uiGridSelectionService.spec.js index 2602c63d0..6e32757f9 100644 --- a/packages/selection/test/uiGridSelectionService.spec.js +++ b/packages/selection/test/uiGridSelectionService.spec.js @@ -247,6 +247,69 @@ describe('ui.grid.selection uiGridSelectionService', function() { grid.api.selection.selectRow(grid.rows[4].entity); expect(grid.rows[4].isSelected).toBe(false); }); + + it('select by key then unselect rows by key in entity, including selecting rows already selected and unselecting rows not selected', function() { + grid.rows[4].entity = {str: 'abc'}; + grid.rows[6].entity = {str: 'def'}; + grid.api.selection.selectRowByKey(true, "str", "abc"); + expect(grid.rows[4].isSelected).toBe(true); + + grid.api.selection.selectRowByKey(true, "str", "def"); + expect(grid.rows[4].isSelected).toBe(true); + expect(grid.rows[6].isSelected).toBe(true); + + grid.api.selection.selectRowByKey(true, "str", "abc"); + expect(grid.rows[4].isSelected).toBe(true); + expect(grid.rows[6].isSelected).toBe(true); + + grid.api.selection.unSelectRowByKey(true, "str", "abc"); + expect(grid.rows[4].isSelected).toBe(false); + expect(grid.rows[6].isSelected).toBe(true); + + grid.api.selection.unSelectRowByKey(true, "str", "abc"); + expect(grid.rows[4].isSelected).toBe(false); + expect(grid.rows[6].isSelected).toBe(true); + + grid.api.selection.unSelectRowByKey(true, "str", "def"); + expect(grid.rows[4].isSelected).toBe(false); + expect(grid.rows[6].isSelected).toBe(false); + + grid.rows[4].enableSelection = false; + grid.api.selection.selectRowByKey(true, "str", "abc"); + expect(grid.rows[4].isSelected).toBe(false); + }); + + it('select by key then unselect rows by key outside entity, including selecting rows already selected and unselecting rows not selected', function() { + grid.rows[4].str = 'abc'; + grid.rows[6].str = 'def'; + + grid.api.selection.selectRowByKey(false, "str", "abc"); + expect(grid.rows[4].isSelected).toBe(true); + + grid.api.selection.selectRowByKey(false, "str", "def"); + expect(grid.rows[4].isSelected).toBe(true); + expect(grid.rows[6].isSelected).toBe(true); + + grid.api.selection.selectRowByKey(false, "str", "abc"); + expect(grid.rows[4].isSelected).toBe(true); + expect(grid.rows[6].isSelected).toBe(true); + + grid.api.selection.unSelectRowByKey(false, "str", "abc"); + expect(grid.rows[4].isSelected).toBe(false); + expect(grid.rows[6].isSelected).toBe(true); + + grid.api.selection.unSelectRowByKey(false, "str", "abc"); + expect(grid.rows[4].isSelected).toBe(false); + expect(grid.rows[6].isSelected).toBe(true); + + grid.api.selection.unSelectRowByKey(false, "str", "def"); + expect(grid.rows[4].isSelected).toBe(false); + expect(grid.rows[6].isSelected).toBe(false); + + grid.rows[4].enableSelection = false; + grid.api.selection.selectRowByKey(false, "str", "abc"); + expect(grid.rows[4].isSelected).toBe(false); + }); }); describe('setSelected function', function() {