Open httpete opened 1 week ago
Thanks for the answer @k-rajat19 ... both are valid points. I know this might not be the answer you are looking for, but there is one more thing you can do (although this might be fragile):
const CustomCheckbox = (props) => {
if (props.inputProps['aria-label'].toLowerCase().includes('select row')) {
return <RadioButton {...props} />;
}
return <Checkbox {...props} />;
};
This is fragile because the aria-label might be different when using a locale.
I overrode the properties, but then the "single select" doesn't take on the radio. It just operates as a checkbox even though it is a radio.
My only workaround is to override the BaseCheckbox but then do this inside there. I found that the checkboxes in the grid rows have a ref, and the ones in the column chooser don't.
import { Checkbox, Radio } from '@mineral/core';
import { forwardRef, useLayoutEffect, useState } from 'react';
export const BaseRadio = forwardRef<HTMLButtonElement | null>((props, ref) => {
if ('indeterminate' in props) {
return null;
}
const [isSingle, setIsSingle] = useState(false);
useLayoutEffect(() => {
if (!ref) {
return;
}
setIsSingle(true);
}, [ref]);
return isSingle ? (
<Radio {...props} ref={ref} />
) : (
<Checkbox {...props} ref={ref} />
);
});
BaseRadio.displayName = 'BaseCheckbox';
~``
Well, in that case I would honestly go for a custom renderCell function in the column definition:
import * as React from 'react';
import {
DataGrid,
GRID_CHECKBOX_SELECTION_COL_DEF,
GridRenderCellParams,
useGridApiContext,
} from '@mui/x-data-grid';
import { useDemoData } from '@mui/x-data-grid-generator';
import { Radio } from '@mui/material';
const CustomSelectionCell = (params: GridRenderCellParams) => {
const apiRef = useGridApiContext();
const isChecked = apiRef.current.getSelectedRows().has(params.row.id);
const handleClick = React.useCallback(() => {
if (isChecked) {
return;
}
apiRef.current.setRowSelectionModel([params.row.id]);
}, [isChecked]);
return <Radio checked={isChecked} onClick={handleClick} />;
};
export default function DisableClickSelectionGrid() {
const { data } = useDemoData({
dataSet: 'Commodity',
rowLength: 10,
maxColumns: 6,
});
const columns = React.useMemo(
() => [
{
...GRID_CHECKBOX_SELECTION_COL_DEF,
renderCell: CustomSelectionCell,
renderHeader: () => null,
},
...data.columns,
],
[data],
);
return (
<div style={{ height: 400, width: '100%' }}>
<DataGrid checkboxSelection disableRowSelectionOnClick columns={columns} rows={data.rows} />
</div>
);
}
if you want to be able to "unselect' a radio you can replace
const handleClick = React.useCallback(() => {
if (isChecked) {
- return;
+ apiRef.current.setRowSelectionModel([]);
+ return;
}
apiRef.current.setRowSelectionModel([params.row.id]);
}, [isChecked]);
So I found subtle differences when I did my own checkbox column in how the selection worked. What you want is clicking anywhere on the row, to highlight and select the radio (just like checkbox). If I clicked the radio directly, it wouldn't work. If I clicked the cell surrounding the radio, it wouldn't work.
The hacky way I ended up with achieved a perfect result. I feel this should be standard behavior, because when you do single selection mode the proper affordance is a radio per row, not a checkbox per row. It does work correctly, but I get hit by our usability experts when it is single select checkbox.
I had to do a little css to hide the "select / deselect all" checkbox in the header when single selection mode.
Can you add this as a feature? Since we support both modes already single or multi, it seems that correcting the control with a radio is the right way.
If I could override the rowSelectionCheckbox slot exclusively that would also fix it.
Ok, the requirement that the rowClick should select a row is actually making this a lot easier:
import * as React from 'react';
import {
DataGrid,
GRID_CHECKBOX_SELECTION_COL_DEF,
GridColDef,
GridRenderCellParams,
useGridApiContext,
useGridApiRef,
} from '@mui/x-data-grid';
import { useDemoData } from '@mui/x-data-grid-generator';
import { Radio } from '@mui/material';
const CustomSelectionCell = (params: GridRenderCellParams) => {
const rowId = params.row.id;
const apiRef = useGridApiContext();
const [isChecked, setIsChecked] = React.useState(
apiRef.current.getSelectedRows().has(params.row.id),
);
React.useEffect(() => {
apiRef.current.subscribeEvent('rowSelectionChange', (newSelectionModel) => {
setIsChecked(newSelectionModel.includes(rowId));
console.log('rowClick', params.row.id, newSelectionModel);
});
}, [apiRef]);
return <Radio checked={isChecked} />;
};
export default function DisableClickSelectionGrid() {
const apiRef = useGridApiRef();
const { data } = useDemoData({
dataSet: 'Commodity',
rowLength: 10,
maxColumns: 6,
});
const columns = React.useMemo(
() => [
{
...GRID_CHECKBOX_SELECTION_COL_DEF,
type: 'custom' as GridColDef['type'],
field: '__radio__',
renderCell: CustomSelectionCell,
renderHeader: () => null,
},
...data.columns,
],
[data],
);
return (
<div style={{ height: 400, width: '100%' }}>
<DataGrid apiRef={apiRef} columns={columns} rows={data.rows} />
</div>
);
}
Try this! :D
Steps to reproduce
Link to live example: (required)
Steps: 1. 2. 3.
Current behavior
I have overridden the baseCheckbox slot with a Radio component which works great in the Single Selection Grid mode. But it is completely unepected for baseCheckbox to override the Column chooser checkbox. In my case, I only want the grid selection mechanism to be a radio, not the column chooser one.
Expected behavior
Should allow me a way to only override the gridRowSelection checkBox.
Context
No response
Your environment
``` Don't forget to mention which browser you used. Output from `npx @mui/envinfo` goes here. ```npx @mui/envinfo
Search keywords: mui baseCheckbox Order ID: 79357