diff --git a/README.md b/README.md
index fd20ba5..2f3bc1a 100644
--- a/README.md
+++ b/README.md
@@ -150,7 +150,7 @@ The widget does not display search filter inputs. To provide search filters, def
- _Use infinite scroll_ - Use infinite scroll rather than the default paging buttons. Set nowrap on the table class!
- _Horizontal scrolling_ - When true, horizontal scrolling is used. Set nowrap on the table class!
- _Vertical scrolling_ - Optional, any CSS unit, default 200px. When specified, vertical scrolling is used and height of the rows is constrained to the specified height
-- _State save name_ - Optional. When specified, grid layout state is saved to and loaded from browser local storage using the specied name. Make sure this name is unique across your application!
+- _State save name_ - Optional. When specified, grid layout state is saved to and loaded from browser local storage using the specied name. Make sure this name is unique across your application! It is also advisable to put your project name first in each statesaving name, to prevent issues where multiple apps have an order overview grid.
#### Column visibility
@@ -181,6 +181,7 @@ The _Selection changed callback microflow_ can be used to create functionality s
- _Selection_ - Selection type
- _Select first row_ - Select first row after displaying data
+- _Allow deselect_ - Allow deselect. When off, at least one row must remain selected.
- _Selection changed callback microflow_ - The name of the microflow (Module.Microflow) that is called when the selection has been changed.
### Buttons
diff --git a/src/DataTables/DataTables.xml b/src/DataTables/DataTables.xml
index de395c2..b13bc2d 100644
--- a/src/DataTables/DataTables.xml
+++ b/src/DataTables/DataTables.xml
@@ -326,6 +326,11 @@
Selection
Select first row after displaying data
+
+ Allow deselect
+ Selection
+ Allow deselect. When off, at least one row must remain selected.
+
Selection changed callback microflow
Selection
diff --git a/src/DataTables/widget/DataTables.js b/src/DataTables/widget/DataTables.js
index 579d32a..b4fcab1 100644
--- a/src/DataTables/widget/DataTables.js
+++ b/src/DataTables/widget/DataTables.js
@@ -76,6 +76,7 @@ define([
scrollY: null,
selectionType: null,
selectFirst: false,
+ allowDeselect: true,
selectionMicroflowName: "",
columnList: null,
attrSearchFilterList: null,
@@ -113,6 +114,7 @@ define([
_sortDir: "",
_exportButton: null,
_scrollerPage: null,
+ _previousSelection: null,
// I18N file names object at the end, out of sight!
@@ -344,7 +346,8 @@ define([
cellNode = dataTablesThisObj.api().cell({row : rowIdx, column : colIdx}).node();
cellNode.setAttribute("data-columnName", tdData.name);
}, this);
- if (thisObj.selectFirst && rowLoop === 0) {
+ // Select the first row, unless there is already a selection. The draw callback can be called multiple times.
+ if (thisObj.selectFirst && rowLoop === 0 && !thisObj._table.rows({selected: true}).any()) {
this.select();
}
});
@@ -475,7 +478,7 @@ define([
this._table
.on("select", function (e, dt, type, indexes) {
if (thisObj.selectionType !== "none") {
- thisObj._setButtonEnabledStatus();
+ thisObj._setButtonEnabledStatus("select");
}
if (thisObj.selectionMicroflowName) {
thisObj._callSelectionMicroflow();
@@ -483,7 +486,7 @@ define([
})
.on("deselect", function (e, dt, type, indexes) {
if (thisObj.selectionType !== "none") {
- thisObj._setButtonEnabledStatus();
+ thisObj._setButtonEnabledStatus("deselect");
}
if (thisObj.selectionMicroflowName) {
thisObj._callSelectionMicroflow();
@@ -793,15 +796,10 @@ define([
});
},
- // Get selected rows
- _getSelectedRowData: function () {
- return this._table.rows({selected: true}).data().toArray();
- },
-
// Get selected rows
_getSelectedRows: function () {
var guids = [],
- rowDataArray = this._getSelectedRowData();
+ rowDataArray = this._table.rows({selected: true}).data().toArray();
dojoArray.forEach(rowDataArray, function (rowData) {
guids.push(rowData.guid);
});
@@ -1237,14 +1235,17 @@ define([
},
// Enable/Disable buttons when selection changes
- _setButtonEnabledStatus: function () {
+ _setButtonEnabledStatus: function (eventName) {
logger.debug(this.id + "._setButtonEnabledStatus");
var attrValue,
buttonDefinition,
buttonEnabled,
hasSelection,
- rowDataArray;
- rowDataArray = this._getSelectedRowData();
+ rowDataArray,
+ selection,
+ thisObj = this;
+ selection = this._table.rows({selected: true});
+ rowDataArray = selection.data().toArray();
hasSelection = (rowDataArray.length > 0);
dojoArray.forEach(this._buttonList, function (button, i) {
if (hasSelection) {
@@ -1278,6 +1279,29 @@ define([
button.setAttribute("disabled", "");
}
}, this);
+ switch (eventName) {
+ case "select":
+ this._previousSelection = selection;
+ break;
+
+ case "deselect":
+ // If there is still a selection or deselection is allowed, just save the selection
+ if (selection.any() || this.allowDeselect) {
+ this._previousSelection = selection;
+ } else {
+ console.log("No selection anymore");
+ setTimeout(function () {
+ if (!thisObj._table.rows({selected: true}).any() && thisObj._previousSelection) {
+ console.log("Reset selection");
+ thisObj._previousSelection.select();
+ }
+ }, 100);
+ }
+ break;
+
+ default:
+ break;
+ }
},
// Reset subscriptions.
diff --git a/test/DataTablesTest.mpr b/test/DataTablesTest.mpr
index e67048d..c22e631 100644
Binary files a/test/DataTablesTest.mpr and b/test/DataTablesTest.mpr differ
diff --git a/test/javasource/datatablestestmodule/proxies/microflows/Microflows.java b/test/javasource/datatablestestmodule/proxies/microflows/Microflows.java
index a84488f..8ce41f6 100644
--- a/test/javasource/datatablestestmodule/proxies/microflows/Microflows.java
+++ b/test/javasource/datatablestestmodule/proxies/microflows/Microflows.java
@@ -388,6 +388,19 @@ public static void oCh_Person_ShowSelectedPerson(IContext context, datatablestes
throw new MendixRuntimeException(e);
}
}
+ public static void oCh_Person_ShowSelectedPerson_NoEmptySelection(IContext context, datatablestestmodule.proxies.Person _person)
+ {
+ try
+ {
+ Map params = new HashMap();
+ params.put("Person", _person == null ? null : _person.getMendixObject());
+ Core.execute(context, "DataTablesTestModule.OCh_Person_ShowSelectedPerson_NoEmptySelection", params);
+ }
+ catch (CoreException e)
+ {
+ throw new MendixRuntimeException(e);
+ }
+ }
public static datatablestestmodule.proxies.DataTableContextEntity sUB_DataTableContextEntity_GetFromSession(IContext context)
{
try
diff --git a/test/widgets/DataTables.mpk b/test/widgets/DataTables.mpk
index c843f0f..7892506 100644
Binary files a/test/widgets/DataTables.mpk and b/test/widgets/DataTables.mpk differ