version my code is using v8.13.1 of mui/x-data-grid with typescript
Scenario/Outcome I am trying to have both an inline button with each row that will filter the frontend table and call the api to call an update on the backend (setting rows as actioned)
I have a function for each row which filters out the row and successfully calls the api
The problem is the buttons for each row works but the button i use in the grid header no matter what way i write it does not filter the grid . At the moment my code will loop through the rows selected and call the same function as the other button so in my mind it should work. I did try moving it all into its own function instead of a wrapper which again the button used on the checkboxes still did not filter the grid.
Code snippets I am a begginer hopefully the below code is enough detail
imports
import React, { useEffect, useState,useRef,useMemo } from "react";
import { DataGrid, type GridColDef, type GridRenderCellParams,type GridRowId,type GridRowSelectionModel,Toolbar,ToolbarButton, } from "@mui/x-data-grid";
import { Button, CircularProgress, Box,FormControl,InputLabel,MenuItem,Select,Tooltip, Stack, } from "@mui/material";
import axios from "axios";
grid setup
const MyDataGrid: React.FC = () => {
const [rows, setRows] = useState<RowData[]>([]);
const [loading, setLoading] = useState<boolean>(true);
const [deletingIds, setDeletingIds] = useState<number[]>([]);
const [filteredRows, setFilteredRows] = useState<RowData[]>([]);
// v8 selection model shape: { type: 'include' | 'exclude', ids: Set<GridRowId> }
const [rowSelectionModel, setRowSelectionModel] = useState<GridRowSelectionModel>({
type: "include",
ids: new Set<GridRowId>(),
});
const [nameFilter, setNameFilter] = useState<string>("All");
// Fetch data from API on mount
useEffect(() => {
// Optimistic delete
const handleDelete = async (id: number) => {
const previousRows = [...rows];
const previousFiltered = [...filteredRows];
// Optimistically update
setRows((prev) => prev.filter((r) => r.id !== id));
setFilteredRows((prev) => prev.filter((r) => r.id !== id));
setDeletingIds((prev) => [...prev, id]);
try {
await axios.post(`urlhereremoved/action/${id}`,'',{
auth: {
username: apiUser,
password: apiPass
}});
console.log(`Deleted row with id ${id}`);
} catch (error) {
//COMMENT OUT AS NOT WORKING ON REMOTE SERVER
// alert("Failed to delete the row. Restoring...");
//setRows(previousRows); // rollback
//setFilteredRows(previousFiltered);
} finally {
setDeletingIds((prev) => prev.filter((delId) => delId !== id));
}
};
the function from delete selected button
const handleDeleteSelected = async () => {
const selectedIds = getSelectedIdsFromModel(rowSelectionModel).map((id) =>
Number(id)
);
if (selectedIds.length === 0) {
alert("No rows selected");
return;
}
console.log(selectedIds)
selectedIds.forEach( (element) => {
handleDelete(element);
});
};
The button in column def that works calls onClick={() => handleDelete(params.row.id)} and the other button calls the following in the custom header
<Button
variant="contained"
color="error"
disabled={getSelectedIdsFromModel(rowSelectionModel).length === 0}
onClick={handleDeleteSelected}
>
Remove Selected
</Button>
finally the grid itself- the delete selected button does pass the correct selected ids
return (
<div style={{ width: "100%" }}>
<DataGrid
rows={filteredRows}
columns={columns}
initialState={{pagination: { paginationModel: { pageSize: 20, page: 0 } }}}
disableRowSelectionOnClick
density="compact"
slots={{ toolbar: CustomToolbar }}
pageSizeOptions={[20,50,100]}
showToolbar
checkboxSelection
rowSelectionModel={rowSelectionModel}
// The new v8 onRowSelectionModelChange receives the same model shape
onRowSelectionModelChange={(newModel) => {
// newModel already has the v8 shape, so accept it directly.
setRowSelectionModel(newModel);
}}
/>
</div>
);
the incline grid button removes row. when passing ids to this from row selected remove button in header the rows are not filtering.