When I hover over any row in the Datagrid, I want the "Analyze" button to change from variant outlined to contained. I cannot get any event to trigger when the row is hovered over, nor can I find any information on how to update/re-render a cell within that row when the mouse is within that row.
"@mui/x-data-grid": "^5.17.25",
"@mui/x-data-grid-generator": "^6.0.0",
"@mui/x-data-grid-pro": "^6.0.0",
import React, { useRef, useState, useEffect } from "react";
import { DataGrid, GridRowsProp, GridColDef } from "@mui/x-data-grid";
import Box from "@mui/material/Box";
import Button from "@mui/material/Button";
import { useTheme } from "@mui/system";
import Link from "next/link";
import TextField from "@mui/material/TextField";
import InputAdornment from "@mui/material/InputAdornment";
import SearchIcon from "@mui/icons-material/Search";
import AddIcon from "@mui/icons-material/Add";
import CircularProgress from "@mui/material/CircularProgress";
import { alpha, styled, lighten } from "@mui/material/styles";
export default function PropertiesList({ newProperties }) {
const theme = useTheme();
const boxRef = useRef(null);
const [searchText, setSearchText] = useState("");
const columns = getColumns(theme);
function getColumns(theme) {
// commented because irrelevant
return [
{
field: "id",
headerName: "Actions",
width: 150,
renderCell: (params) => {
return (
<Box
sx={{
display: "flex",
justifyContent: "space-between",
width: "100%"
}}
>
<Link
href="/properties/[id]"
as={`/properties/${params.row.original_doc || params.row.id}`}
>
<Button
size="small"
variant="outlined"
startIcon={<CalculateIcon />}
sx={{
backgroundColor:
hoveredRowId === params.id
? theme.palette.success.main
: ""
}}
>
Analyze
</Button>
</Link>
</Box>
);
}
}
];
}
useEffect(() => {
if (!boxRef.current) return;
const screenHeight = window.innerHeight;
boxRef.current.style.height = `${screenHeight - 120}px`;
}, []);
const handleRowOver = (params) => {
// change the analyze button from "outlined" to "contained" when hovered.
// The below console.log does not trigger.
console.log(`Row ${params.id} is being hovered over`);
};
return (
<Box ref={boxRef}>
{!newProperties && (
<Box
sx={{
height: "calc(100vh - 160px)",
display: "flex",
justifyContent: "center",
alignItems: "center"
}}
>
<CircularProgress size={32} />
</Box>
)}
{newProperties && (
<>
<Box
sx={{
display: "flex",
justifyContent: "space-between",
alignItems: "center",
background: theme.palette.background.background2,
marginTop: 3,
// marginBottom: 1,
padding: 2,
border: "1px solid " + theme.palette.contrast.contrast1,
borderTopLeftRadius: 8,
borderTopRightRadius: 8
}}
>
<TextField
label="Search for property"
placeholder=""
sx={{ marginTop: 1, marginBottom: 1 }}
onChange={(event) => setSearchText(event.target.value)}
InputProps={{
startAdornment: (
<InputAdornment position="start">
<SearchIcon />
</InputAdornment>
)
}}
/>
<Link href="/properties/add">
<Button
size="medium"
variant="contained"
sx={{ height: 50 }}
startIcon={<AddIcon />}
>
Add Property
</Button>
</Link>
</Box>
<DataGrid
rowMouseEnter={handleRowOver}
sx={{
border: "1px solid " + theme.palette.contrast.contrast1,
height: "calc(100vh - 280px)",
background: theme.palette.background.background1,
"& .MuiDataGrid-virtualScroller::-webkit-scrollbar": {
height: "0.4em",
width: "0.4em"
},
"& .MuiDataGrid-virtualScroller::-webkit-scrollbar-track": {
background: theme.palette.contrast.contrast1
},
"& .MuiDataGrid-virtualScroller::-webkit-scrollbar-thumb": {
backgroundColor: theme.palette.contrast.contrast2
},
"& .MuiDataGrid-virtualScroller::-webkit-scrollbar-thumb:hover": {
background: theme.palette.contrast.default
},
borderTopLeftRadius: 0,
borderTopRightRadius: 0,
borderBottomLeftRadius: 8,
borderBottomRightRadius: 8
}}
rows={newProperties.filter(
(row) =>
(row.address &&
row.address
.toLowerCase()
.includes(searchText.toLowerCase())) ||
(row.city &&
row.city.toLowerCase().includes(searchText.toLowerCase())) ||
(row.state &&
row.state.toLowerCase().includes(searchText.toLowerCase())) ||
(row.zip &&
row.zip
.toString()
.toLowerCase()
.includes(searchText.toLowerCase()))
)}
columns={columns}
pageSize={13}
disableColumnFilter
disableSelectionOnClick
disableColumnSelector
/>
</>
)}
</Box>
);
}
2
Answers
The MUI DataGrid does not include any event function regarding hovering.
(You only have functions like
onCellClick()
,onCellEditStart()
,onCellKeyDown()
, …)I thought about event Listener like
onMouseEnter
andonMouseLeave
, but, as mentioned here, that it will cause so many renders.Maybe using the sx prop would help to style those blocks with
:hover
:Something like:
Associated with
(not
rowMouseEnter
)Using a similar idea as the one show in DataGrid row:
with:
When you hover over a row in the DataGrid, the
handleRowOver
function will be called, and you can see the log in the browser console.When the mouse leaves the row, the anonymous function will print a message.
The hover effect for the "Analyze" button will still be handled by the
:hover
pseudo-class in thesx
prop.As @VonC mentioned in his answer, you can use slotProps to pass props to a row element, in particular onMouseEnter and onMouseLeave. Using the technique described here, I was able to reproduce the behavior you are trying to achieve in a fairly concise manner.
The main idea is to fire an event inside onMouseEnter and onMouseLeave that we will subscribe to in our custom button component.
In order to achieve isolation of events between different rows, we will include the row id in the event name.
It was difficult to run your component without a context, so to demonstrate the principle, I built a minimal DataGrid myself.
You can see a live example here:
Code: