Info
I have a project that is using React, Redux, and MUI-Datatables. A simple demo for this project can be found at this CodeSandbox.
In this app, there are two main components, a map and a datatable. The two communicate via redux so that when a row is selected in the table, the respective circle in the map is highlighted and vice versa.
Problem
My problem is with the indeterminate toggle selectAll checkbox on the table. When the user has selected a row then applies a filter, the selectAll checkbox shows the '-' indeterminate symbol, but nothing happens when it is clicked.
Steps to recreate:
- User selects the first row in the table, circle1.
- User opens filter dialog in right-hand corner of table.
- From the Marker dropdown menu in the filter dialog, User selects circle3 as the filter value.
- User closes filter dialog
- User clicks on selectAll checkbox at the top of the select row column. It will be showing the '-' symbol.
- Notice that nothing changes. No rows are selected or deselected.
Desired Behavior:
When the User has selected a row in the table then applies a filter, the selectAll checkbox should still select all visible rows on first click and deselect all on second click the same way it normally would.
Code
Live: CodeSandbox
Table Component:
import React, { useEffect, useState } from "react";
import MUIDataTable from "mui-datatables";
import { connect } from "react-redux";
import { handleSelection } from "./redux";
import circles from "./assets/data/circles";
import { addToOrRemoveFromArray } from "./utils";
// Table component
const Table = ({ handleSelection, selections }) => {
const [selectionIndexes, setSelectionIndexes] = useState([]);
// When 'selections' changes in redux store:
useEffect(() => {
let indexes = [];
// Iterate selections:
selections.forEach((selection) => {
// Push the index of the selected
// circle into index arr:
let index = circles.indexOf(selection);
indexes.push(index);
});
// Set selections to local state hook:
setSelectionIndexes(indexes);
}, [selections]);
// Table options:
const options = {
rowsSelected: selectionIndexes, // User provided array of numbers (dataIndexes) which indicates the selected rows
selectToolbarPlacement: "none",
selectableRows: "multiple", // Enable selection of multiple rows
setRowProps: (row, dataIndex, rowIndex) => {
return {
style: {
padding: ".5rem",
margin: ".5rem auto"
}
};
},
// When a row(s) is/are selected:
onRowSelectionChange: (
currentRowsSelected,
allRowsSelected,
rowsSelected
) => {
let temp = [];
let indexes = [];
// Iterate rowsSelected:
rowsSelected.forEach((row) => {
// Add or remove row index to/from indexes arr:
indexes = addToOrRemoveFromArray(row, indexes, "indexes");
// Circle data:
let circle_data = circles[row];
// Add or remove circle_data to/from temp arr:
temp = addToOrRemoveFromArray(circle_data, temp, "temp");
});
// Set indexes to local hook:
setSelectionIndexes(indexes);
// Send the circle data to redux:
handleSelection(temp);
}
};
const columns = [
{
name: "marker",
label: "Marker",
options: {
filter: true,
sort: false
}
},
{
name: "lat",
label: "Latitude",
options: {
filter: true,
sort: false
}
},
{
name: "lon",
label: "Longitude",
options: {
filter: true,
sort: false
}
},
{
name: "radius",
label: "Radius",
options: {
filter: true,
sort: false
}
}
];
const table_name = `Circle Markers`;
return (
<>
<div style={{ display: "table", tableLayout: "fixed", width: "100%" }}>
<MUIDataTable
title={<h3>{table_name}</h3>}
data={circles}
columns={columns}
options={options}
/>
</div>
</>
);
};
const mapStateToProps = (state) => {
return {
selections: state.selection.selections
};
};
const mapDispatchToProps = (dispatch) => {
return {
handleSelection: (selections) => dispatch(handleSelection(selections))
};
};
export default connect(mapStateToProps, mapDispatchToProps)(Table);
How can I get the selectAll checkbox to work properly when a row outside of the filtered data has been selected?
Is it ok to de-select the selected row when filters applied? I did a workaround to meet the desired behavior.
Live Code: CodeSandBox
I added additional code in Table.jsx line 34