I am using Tabulator (v6.3) and facing a conflict between the selectableRange module and the rowSelection formatter (checkbox).
The Goal: I want to use Excel-like range selection (selectableRange: 1) for cell operations, but also use a checkbox column (formatter: "rowSelection") for selecting multiple rows.
The Problem: I am trying to implement a checkbox column using a custom formatter to prevent the selectableRange click conflict. I added e.stopPropagation() to the checkbox click/mousedown events to stop the range selection logic from clearing other rows.
Current Behavior:
It seems that even though I stopped the event propagation, calling row.toggleSelect() programmatically still triggers Tabulator's internal single-selection logic enforced by selectableRange: 1. This creates a desync where the UI shows multiple selections, but the internal data only holds one.
My Constraints:
I cannot modify the existing getSelectedData() calls in my legacy codebase. The native selection API must work.
I need selectableRange for cell copying and rowSelection for multi-row actions to coexist.
Question: Is there a configuration option or a workaround to isolate the rowSelection column from the selectableRange logic? I need the checkboxes to toggle row selection additively without clearing the existing selection, while keeping selectableRange active for other columns.
// Data: Minimal set to reproduce the issue
var tableData = [
{id:1, name:"Oli Bob", age:12},
{id:2, name:"Mary May", age:1},
{id:3, name:"Christine Lobowski", age:42},
];
// Custom Formatter to stop event propagation
var customRowSelection = function(cell, formatterParams, onRendered){
var checkbox = document.createElement("input");
checkbox.type = 'checkbox';
// Attempting to sync with row selection
checkbox.checked = cell.getRow().isSelected();
// Trying to stop the range selection trigger
var stopEvent = function(e){ e.stopPropagation(); }
checkbox.addEventListener("pointerdown", stopEvent);
checkbox.addEventListener("mousedown", stopEvent);
checkbox.addEventListener("click", function(e){
e.stopPropagation();
cell.getRow().toggleSelect();
});
return checkbox;
};
// Tabulator Configuration
var table = new Tabulator("#example-table", {
data: tableData,
height: "200px",
// 1. Enabling Range Selection (The core of the conflict)
selectableRange: 1,
selectableRangeColumns: true,
selectableRangeRows: true,
// 2. Disabling Default Row Selection logic
selectable: false,
columns:[
{
// Custom checkbox column
formatter: customRowSelection,
width: 50,
hozAlign: "center",
headerSort: false
},
{title:"Name", field:"name", width:200},
{title:"Age", field:"age"},
],
});
// Issue: Even with stopPropagation, clicking the checkbox seems to trigger
// the internal range selection logic, clearing other selected rows.
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/tabulator-tables@6.3.1/dist/js/tabulator.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/tabulator-tables@6.3.1/dist/css/tabulator.min.css" rel="stylesheet"/>
<div id="example-table"></div>
I was able to get it to work by modifying your custom formatter to manually select and unselect rows using jQuery to check the state of the checkbox that was clicked. I could not find the reason why the toggleSelect() clears the selected rows nor was I able to find a configuration that would allow it to work.
var customRowSelection = function(cell, formatterParams, onRendered){
var checkbox = document.createElement("input");
checkbox.type = 'checkbox';
checkbox.id = 'row_' + cell.getRow().getPosition();
checkbox.addEventListener("click", function(e){
if($('#' + e.target.id).is(":checked")) {
table.selectRow(cell.getRow().getData().id);
} else {
table.deselectRow(cell.getRow().getData().id);
}
});
return checkbox;
};