Reputation: 3
In my application, there is an MUI Data Grid. In each row, there are 3 custom components: RowSlider
, RowDate
, and RowLock
implementing the MUI Components Slider
, Date Picker
and Button
respectively.
Visualization of the Data Grid
The components Slider
and Date Picker
both have an attribute called disabled
like so:
(The *s are for easier visualization)
<Slider defaultValue={3} step={1} marks min={1} max={5} ***disabled={rowStates[rowIndex]}***/>
The functionality I want to achieve is that when the Lock Button is pressed, it will set the disabled
attribute to true
for both components and when pressed again will set it to false
and so on and so forth.
I want this functionality scoped to each row, i.e., I do not want the "Lock button" in one row to affect the disabled
attribute for components in another row
Right now, my problem is that I cannot find a way to obtain a row index from the MUI Data Grid.
This is what my column declarations for the Data Grid looks like:
import * as React from 'react';
import { GridColDef, GridCellParams } from '@mui/x-data-grid';
import RowDate from '../ui/table/row-date/RowDate';
import RowLock from '../ui/table/row-lock/RowLock';
import RowSlider from '../ui/table/row-slider/RowSlider';
export const columns: GridColDef[] = [
{field: 'id', headerName: 'ID', flex: 1, headerClassName: 'header-cell', cellClassName: 'body-cell'},
{field: 'word', headerName: 'Word', flex: 1, headerClassName: 'header-cell', cellClassName: 'body-cell' },
{field: 'romanization', headerName: 'Romanization', flex: 1, headerClassName: 'header-cell', cellClassName: 'body-cell'},
{field: 'definition', headerName: 'Definition', flex: 1, headerClassName: 'header-cell', cellClassName: 'body-cell'},
{field: 'comfortability', headerName: 'Comfortability', flex: 1, headerClassName: 'header-cell', cellClassName: 'body-cell',
renderCell: (params) => {
return(
<RowSlider rowIndex={params.rowNode.depth}></RowSlider>
);
}
},
{field: 'lastModified', headerName: 'Last Checked', flex: 1, headerClassName: 'header-cell', cellClassName: 'body-cell',
renderCell: (params) => {
return(
<RowDate rowIndex={params.rowNode.depth}></RowDate>
);
}
},
{field: 'lock', headerName: 'Lock', flex: 1, headerClassName: 'header-cell', cellClassName: 'body-cell',
renderCell: (params) => {
return(
<RowLock rowIndex={params.rowNode.depth}></RowLock>
);
}
},
]
export interface TableRow {
id: number,
word: string;
romanization: string,
definition: string;
comfortability: number;
lastModified: Date | null;
lock: boolean;
};
As you can see, I need to be able to pass in the Data Grid "Row Index" (if it exists) into these components as a prop but I have not found a way to do so.
I am planning on tying this index to a React Context
declared inside Table.tsx
:
import * as React from 'react';
import { createContext, useContext } from 'react';
import { Box, alpha, styled } from '@mui/material';
import { DataGrid, GridToolbar, GridRowsProp, GridColDef, gridClasses, GridFilterModel, GridColumnVisibilityModel} from '@mui/x-data-grid';
import { columns} from '../../data/DataInterface';
import { data } from '../../data/Data';
import { DataTable } from './styled-data-grid/StyledDataGrid';
const RowStateContext = createContext<{ rowStates: boolean[]; setRowState: (index: number, value: boolean) => void } | undefined>(undefined);
export const useRowStateContext = () => {
const context = useContext(RowStateContext);
return context;
};
export default function Table() {
const [rowStates, setRowStates] = React.useState<boolean[]>(Array(data.length).fill(false)); // Initialize rowStates array
const setRowState = (index: number, value: boolean) => {
const newStates = [...rowStates];
newStates[index] = value;
setRowStates(newStates);
};
const [filterModel, setFilterModel] = React.useState<GridFilterModel>({
items: [],
quickFilterExcludeHiddenColumns: false,
quickFilterValues: [],
});
const [columnVisibilityModel, setColumnVisibilityModel] = React.useState<GridColumnVisibilityModel>({});
return(
<RowStateContext.Provider value={{ rowStates, setRowState }}> // Provide row state context
<DataTable
checkboxSelection
columns={columns}
columnVisibilityModel={columnVisibilityModel}
disableColumnFilter
disableDensitySelector
disableRowSelectionOnClick
filterModel={filterModel}
getRowClassName={(params) =>
params.indexRelativeToCurrentPage % 2 === 0 ? 'even' : 'odd'
}
onColumnVisibilityModelChange={(newModel) =>
setColumnVisibilityModel(newModel)
}
onFilterModelChange={(newModel) => setFilterModel(newModel)}
rows={data}
slots={{ toolbar: GridToolbar }}
slotProps={{ toolbar: { showQuickFilter: true } }}
/>
</RowStateContext.Provider>
);
}
As of right now, the functionality I am able to produce is that, pressing one of the Lock buttons results in all components in every row being disabled, i.e., its not scoped.
I believe the solution lies within the column declarations within the renderCell
property:
{field: 'lock', headerName: 'Lock', flex: 1, headerClassName: 'header-cell', cellClassName: 'body-cell',
renderCell: (params) => {
return(
<RowLock rowIndex={params.rowNode.depth}></RowLock>
);
}
},
However, I don't know how to do this. As you can see with rowNode.depth
being my latest (lazy) attempt. If I need to switch over to a Data Table
instead of a Data Grid
please let me know to (if it would be easier)
Upvotes: 0
Views: 1141
Reputation: 302
I implemented a solution using hooks. Let me know if this works. MuiDataGridLock
Upvotes: 0