-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[DataGrid] Add possibility to pass in component for row and cell #2138
Comments
For cells, you can use the |
@dtassone Hmm but that only renders stuff inside the cell - it does not change the cell element. In the above example a So basically like you do with Typography - you can provide a
This would really help us in our app! 👍🏻 |
We can add a new To listen for click events made by the middle button, there's a workaround involving attaching an export default function Basic() {
const [gridRoot, setGridRoot] = React.useState(null);
React.useEffect(() => {
const handleAuxClick = (event) => {
if (event.button === 1) {
console.log("middle click");
}
};
if (gridRoot) {
gridRoot.addEventListener("auxclick", handleAuxClick);
}
return () => {
if (gridRoot) {
gridRoot.removeEventListener("auxclick", handleAuxClick);
}
};
}, [gridRoot]);
const handleRef = (el) => {
setGridRoot(el);
};
return (
<div style={{ height: 250, width: "100%" }}>
<DataGrid
ref={handleRef}
columns={[{ field: "name" }]}
rows={[
{ id: 1, name: "React" },
{ id: 2, name: "Material-UI" }
]}
onAuxClick={(event) => console.log(event)}
/>
</div>
);
} |
Thank you @m4theushw for the suggestion I was scratching my head for a while to figure out why your example doesn't work in our case - one tiny detail is missing: the scrollbar Once it is present the middle mouse button event doesn't seem to be fired anymore in the table body 😢 Here is a test codesandbox: https://f4d2y.csb.app/ Do you have an idea? EDIT: I guess I need to go with the regular old mousedown then? |
Arrgh - using the middle click to trigger a window.open() will not open it in the background as it would when the event is just fired on a link - so then back to square one it would be great if we can overwrite the row to become a link so that the event is formed correctly 😕 |
You have to call |
OK let me describe the bigger picture that I am actually trying to achieve: Now I can add an anchor element to each and every cell to get the behaviour that I want, since middle clicking an anchor behaves correctly - but this will unnecessarily pollute the DOM with hundreds of links when instead I could (via |
@Primajin Ok thanks for the extra detail of the use case. So you are actually not looking for being able to do ⬆️. If you do, you would have https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a. Based on https://stackoverflow.com/questions/17147821/how-to-make-a-whole-row-in-a-table-clickable-as-a-link, you might not be able to implement it the way to have tried. Stripe's dashboard implements what you are looking for by rendering this DOM structure: The thread makes me think a bit of #1912 (comment) |
Hmm for Would a And pardon the heretic question - since it's a div grid and not a real |
@Primajin Columns and rows are virtualized. Does x100 more
There are cells where you wouldn't want as a link wrapper: a > button is KO too. For instance, the column for checkbox selection, the column for actions. But yeah, if we expose enough parameters so you can conditionally render, it could work. It could work equally if you have a wrapper on top of your renderCell? |
Yeah I guess that could work - I think I will need to play a bit more with this during my next workdays 👍🏻 |
Yeah so I ended up with a const onCellClick = event => {
const middleMouse = event.button === 1;
if (middleMouse) {
event.stopPropagation();
} else {
event.preventDefault();
}
}; and then the rest is handled by onRowClick 🤷🏻 and for the css I went with link: {
color: 'inherit',
display: 'flex',
textDecoration: 'inherit',
}, |
A possible solution: diff --git a/packages/grid/_modules_/grid/components/cell/GridCell.tsx b/packages/grid/_modules_/grid/components/cell/GridCellOwner.tsx
similarity index 96%
rename from packages/grid/_modules_/grid/components/cell/GridCell.tsx
rename to packages/grid/_modules_/grid/components/cell/GridCellOwner.tsx
index 2fba02dd..3c0fa6c0 100644
--- a/packages/grid/_modules_/grid/components/cell/GridCell.tsx
+++ b/packages/grid/_modules_/grid/components/cell/GridCellOwner.tsx
@@ -21,7 +21,7 @@ import { GRID_CSS_CLASS_PREFIX } from '../../constants/cssClassesConstants';
import { GridAlignment, GridCellMode, GridCellValue, GridRowId } from '../../models/index';
import { useGridApiContext } from '../../hooks/root/useGridApiContext';
-export interface GridCellProps {
+export interface GridCellOwnerProps {
align: GridAlignment;
className?: string;
colIndex: number;
@@ -41,7 +41,7 @@ export interface GridCellProps {
tabIndex: 0 | -1;
}
-export const GridCell = React.memo(function GridCell(props: GridCellProps) {
+export const GridCellOwner = React.memo(function GridCellOwner(props: GridCellOwnerProps) {
const {
align,
className,
@@ -162,7 +162,7 @@ export const GridCell = React.memo(function GridCell(props: GridCellProps) {
});
return (
- <div
+ <components.Cell
ref={cellRef}
className={cssClasses}
role="cell"
@@ -179,6 +179,6 @@ export const GridCell = React.memo(function GridCell(props: GridCellProps) {
{...eventsHandlers}
>
{children || valueToRender?.toString()}
- </div>
+ </components.Cell>
);
});
diff --git a/packages/grid/_modules_/grid/models/gridSlotsComponent.ts b/packages/grid/_modules_/grid/models/gridSlotsComponent.ts
index 16d66352..35e8f81c 100644
--- a/packages/grid/_modules_/grid/models/gridSlotsComponent.ts
+++ b/packages/grid/_modules_/grid/models/gridSlotsComponent.ts
@@ -120,6 +120,7 @@ export const DEFAULT_GRID_SLOTS_COMPONENTS: GridApiRefComponentsProperty = {
ErrorOverlay,
FilterPanel: GridFilterPanel,
Footer: GridFooter,
+ Cell: GridCell,
Header: GridHeader,
PreferencesPanel: GridPreferencesPanel,
LoadingOverlay: GridLoadingOverlay, We would likely need to create a new In practice, it would mean that:
|
Yeah so that would allow passing in your own component like one is used from Composition here right? import { Link } from 'react-router-dom';
function ListItemLink(props) {
const { icon, primary, to } = props;
const CustomLink = props => <Link to={to} {...props} />;
return (
<li>
<ListItem button component={CustomLink}>
<ListItemIcon>{icon}</ListItemIcon>
<ListItemText primary={primary} />
</ListItem>
</li>
);
} Shall I open the MR for this, or would you like to? How do we go from here? 😃 |
@Primajin Correct. I suspect that we would need an extra prop to host the context: the row's data, the field, the column. For this, maybe we should leverage mui/material-ui#27127. |
Sounds good to me - I am happy to let this cook a while longer until we figure out a good and consistent way to solve it. |
Summary 💡
With many material UI components I can overwrite what element should be rendered in the end.
Passing in components allows me to pass in a special checkbox component via https://material-ui.com/api/data-grid/data-grid/#slots but no component for the rows and cells themselves.
Examples 🌈
should give me something like
Motivation 🔦
I would like to have rows / cells rendered as something else than a div and thus provide an element via components
For example to attach to the middle mouse click the row should be an anchor that I can point to the detail page of the data. A mere onClick handler doesn't fire the event.
Order id 💳
ORDER:25229
The text was updated successfully, but these errors were encountered: