Suroor Ahmmad
Suroor Ahmmad

Reputation: 1162

How to implement search in material-ui datagrid?

I'm trying to implement quick filter/search option in Material-UI datagrid. As of now datagrid doesn't have search option. I'm using Material-UI-Search-Bar library to add search field and functionality. I'm having this inside custom toolbar, but unfortunately this doesn't work because it has something to do with state. I'm not able to focus the text field. Below my code

...

const requestSearch = (searchedVal: string) => {
    const filteredRows = tableData.filter((o: any) => {
        return Object.keys(o).some((k: any) => {
            return  o[k].toString().toLowerCase().indexOf(searchedVal.toLowerCase()) != -1;
        })
    });
    console.log(filteredRows);
    // setTableData(filteredRows);
};

const cancelSearch = () => {
    setSearchText("");
    requestSearch(searchText);
};

const CustomToolbar = () => {
    <div className='p-6'>
        <div> ... </div>
        <SearchBar
            value={searchText}
            onChange={(searchVal: string) => requestSearch(searchVal)}
            onCancelSearch={() => cancelSearch()}
         />
    </div>
}
...
return (
    <div ... >
        <div style={{ height: 500, width: '100%', backgroundColor: 'white' }}>
            <DataGrid
                rows={tableData}
                columns={columns}
                components={{ Toolbar: CustomToolbar }}
                ...
             />
        </div>
    </div>
)

Upvotes: 5

Views: 30561

Answers (3)

Muhammad Muzamil
Muhammad Muzamil

Reputation: 1242

In MUI data grid quick search is not very prominent in the documentation but they have added in running demo examples. You just need to add this prop to the data grid and you are done. even you can set debouncing time here.

componentsProps={{
   toolbar: {
       showQuickFilter: true,
          quickFilterProps: { debounceMs: 500 },
    },
 }}

Upvotes: 9

Piyush Sinha
Piyush Sinha

Reputation: 129

Sometimes Material-UI-Search-Bar library breaks so it's better to use this:

import * as React from 'react';
import IconButton from '@mui/material/IconButton';
import TextField from '@mui/material/TextField';
import {
  DataGrid,
  GridToolbarDensitySelector,
  GridToolbarFilterButton,
} from '@mui/x-data-grid';
import { useDemoData } from '@mui/x-data-grid-generator';
import ClearIcon from '@mui/icons-material/Clear';
import SearchIcon from '@mui/icons-material/Search';
import { createTheme } from '@mui/material/styles';
import { createStyles, makeStyles } from '@mui/styles';

function escapeRegExp(value: string): string {
  return value.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
}

const defaultTheme = createTheme();
const useStyles = makeStyles(
  (theme) =>
    createStyles({
      root: {
        padding: theme.spacing(0.5, 0.5, 0),
        justifyContent: 'space-between',
        display: 'flex',
        alignItems: 'flex-start',
        flexWrap: 'wrap',
      },
      textField: {
        [theme.breakpoints.down('xs')]: {
          width: '100%',
        },
        margin: theme.spacing(1, 0.5, 1.5),
        '& .MuiSvgIcon-root': {
          marginRight: theme.spacing(0.5),
        },
        '& .MuiInput-underline:before': {
          borderBottom: `1px solid ${theme.palette.divider}`,
        },
      },
    }),
  { defaultTheme },
);

interface QuickSearchToolbarProps {
  clearSearch: () => void;
  onChange: () => void;
  value: string;
}

function QuickSearchToolbar(props: QuickSearchToolbarProps) {
  const classes = useStyles();

  return (
    <div className={classes.root}>
      <div>
        <GridToolbarFilterButton />
        <GridToolbarDensitySelector />
      </div>
      <TextField
        variant="standard"
        value={props.value}
        onChange={props.onChange}
        placeholder="Search…"
        className={classes.textField}
        InputProps={{
          startAdornment: <SearchIcon fontSize="small" />,
          endAdornment: (
            <IconButton
              title="Clear"
              aria-label="Clear"
              size="small"
              style={{ visibility: props.value ? 'visible' : 'hidden' }}
              onClick={props.clearSearch}
            >
              <ClearIcon fontSize="small" />
            </IconButton>
          ),
        }}
      />
    </div>
  );
}

export default function QuickFilteringGrid() {
  const { data } = useDemoData({
    dataSet: 'Commodity',
    rowLength: 100,
    maxColumns: 6,
  });
  const [searchText, setSearchText] = React.useState('');
  const [rows, setRows] = React.useState<any[]>(data.rows);

  const requestSearch = (searchValue: string) => {
    setSearchText(searchValue);
    const searchRegex = new RegExp(escapeRegExp(searchValue), 'i');
    const filteredRows = data.rows.filter((row: any) => {
      return Object.keys(row).some((field: any) => {
        return searchRegex.test(row[field].toString());
      });
    });
    setRows(filteredRows);
  };

  React.useEffect(() => {
    setRows(data.rows);
  }, [data.rows]);

  return (
    <div style={{ height: 400, width: '100%' }}>
      <DataGrid
        components={{ Toolbar: QuickSearchToolbar }}
        rows={rows}
        columns={data.columns}
        componentsProps={{
          toolbar: {
            value: searchText,
            onChange: (event: React.ChangeEvent<HTMLInputElement>) =>
              requestSearch(event.target.value),
            clearSearch: () => requestSearch(''),
          },
        }}
      />
    </div>
  );
}

If the demo is not enough and a native version should be implemented, please go to #2842 and upvote.

Upvotes: 6

Related Questions