mui / mui-x

MUI X: Build complex and data-rich applications using a growing list of advanced React components, like the Data Grid, Date and Time Pickers, Charts, and more!
https://mui.com/x/
4.53k stars 1.32k forks source link

Allow ColumnMenuIcon to open a filter panel directly #5627

Open eric-personal opened 2 years ago

eric-personal commented 2 years ago

Duplicates

Latest version

Summary 💡

I'd like to be able to create a custom ColumnMenuIcon that would open a filter panel directly instead of opening the menu. I have attempted this based on the docs but it's not working exactly how I thought it might. See example codesnadbox below.

In the sandbox I'm giving dataGrid a custom ColumnMenuIcon. In that component I use apiRef to open the filter panel. This kind of works but the button is not triggering all the time. The real problem is I only want this to trigger on the name column and all the other columns should act with the default behavior. ColumnMenuIcon does not get any props to show what column its in so the above solution may not work anyway.

What would be the best way to go about having the ColumnMenuIcon trigger the filter panel directly ?

Examples 🌈

codesandbox link

Motivation 🔦

No response

Order ID 💳 (optional)

No response

alexfauquette commented 2 years ago

The ColumnMenuIcon is made for customization of the column, not for logic modification. By using it you only modify the icon, not the IconButton wrapping it.

I'm not aware of an easy way to do that

You can modify <GridColumnHeaderFilterIconButton/> which as a slot such that for column "name", even if the filter counter is 0 you display the filter icon button

This implies copyi-past the component code in your codebase and modifying the following lines: https://github.com/mui/mui-x/blob/4dabd10c9b264ea83e8425a168e7086985bf242d/packages/grid/x-data-grid/src/components/columnHeaders/GridColumnHeaderFilterIconButton.tsx#L62-L64

But I do not know how to remove the column menu on a single column. Maybe we should add a slot for ColumnHeaderMenuIconButton as we have already done for ColumnHeaderFilterIconButton

eric-personal commented 2 years ago

Thanks @alexfauquette, I definitely second your last comment and would be great if the team could add a slot for ColumnHeaderMenuIconButton in the near future. In the meantime I'm going to update GridColumnHeaderFilterIconButton and play around with it.

eric-personal commented 2 years ago

Found a solution that might help folks around this. In your columns setup use the renderHeader to wrap the cell in a custom component. This custom component adds a icon that opens the filter panel.

Example: columns setup:

  const columns = [
      {
        field: "col1",
        headerName: "Blaaaaa",
      },
      {
        field: "col2",
        headerName: "name",
        disableColumnMenu: true,
        renderHeader: (params) => {
          return <FilterColumnWrapper params={params} />;
        },
      },
    ]

Custom FilterColumnWrapper.js

import React, { useCallback } from "react";
import styled from "styled-components/macro";
import IconButton from "@mui/material/IconButton";
import MoreVertIcon from "@mui/icons-material/MoreVert";
import { useGridApiContext } from "@mui/x-data-grid";

const FilterColumnWrapper = ({ params }) => {
  const apiRef = useGridApiContext();
  const onMenuIconClick = useCallback(
    (event) => {
      event.preventDefault();
      event.stopPropagation();
      apiRef.current.showFilterPanel(params.field);
    },
    [apiRef, params.field]
  );
  return (
    <ColumnWrapper>
      <span>{params.colDef.headerName}</span>
      <MenuIconButton className="MuiDataGrid-menuIcon">
        <IconButton
          tabIndex={-1}
          size="small"
          onClick={onMenuIconClick}
          aria-label={apiRef.current.getLocaleText("columnMenuLabel")}
          title={apiRef.current.getLocaleText("columnMenuLabel")}
        >
          <MoreVertIcon style={{ fontSize: "inherit" }} />
        </IconButton>
      </MenuIconButton>
    </ColumnWrapper>
  );
};

const ColumnWrapper = styled.div`
  display: flex;
  justify-content: space-between;
  width: 100%;
`;

const MenuIconButton = styled.div`
  display: flex;
  align-items: center;
  font-size: 16px;
  margin-right: -10px;
`;
export default FilterColumnWrapper;