Easily Add Search and Filter to MUI Table

A search bar on a UI table is a feature many users have come to expect. However, the Material-UI Table component does not have an out-of-the-box search feature. The React community has created several Material-UI search bar examples and solutions, two of which I will discuss in this article.

Material-UI Table with search
MUI Table Search

There is also no filter by default, and so I looked at a few 3rd party libraries for filtering. Two of them only offer filters, but I can’t recommend either of them. However, material-table has a great filter feature.

My recommendation for MUI Table search and filter:

Code Sandbox link with full React code is in the Resources section. These MUI posts will also be helpful:

Watch the YouTube version of this article or watch the embedded video below.

The Easiest Way to Add a Search Bar...
The Easiest Way to Add a Search Bar to Material-UI Table

Material-UI-Search-Bar Table Search Example

If you need a no-frills search bar to inject above a React Material-UI Table component, material-ui-search-bar is a great option. It is a library that simply provides this one component, and as such, is light weight. The documentation is here, but the library’s npm download page has some helpful documentation as well.

Let’s take a look at how to use this component with a search that runs when the users types in or clears the search box. First, the JSX:

import SearchBar from "material-ui-search-bar";

//....

return (
<Paper>
  <SearchBar
    value={searched}
    onChange={(searchVal) => requestSearch(searchVal)}
    onCancelSearch={() => cancelSearch()}
  />
  <TableContainer>
    <Table className={classes.table} aria-label="simple table">
    //more JSX
    </Table>
  </TableContainer>
)

It’s tidy and concise, exactly what I want. Notice that I include the SearchBar component inside a Paper wrapper so that it visually looks like it is part of the table.

You can see I have a few values and functions I need to add: searched, requestSearch, and cancelSearch. Take a look at the below:

export default function BasicTable() {
  const [rows, setRows] = useState<food[]>(originalRows);
  const [searched, setSearched] = useState<string>("");
  const classes = useStyles();

  const requestSearch = (searchedVal: string) => {
    const filteredRows = originalRows.filter((row) => {
      return row.name.toLowerCase().includes(searchedVal.toLowerCase());
    });
  setRows(filteredRows);
};

const cancelSearch = () => {
  setSearched("");
  requestSearch(searched);
};

I use the useState hook to maintain state for the current search string and to maintain the state of filtering on the rows.

The filter is a simple includes . For most projects, you will likely have data from a query that gets filtered here, or you passed the search string to the back end and handled filtering there. This demo is really about the simplicity of the JSX and JS functions when using material-ui-search-library.

Let’s tie it all together with a glimpse at the data:

interface food {
  name: string;
  calories: number;
  fat: number;
  carbs: number;
  protein: number;
}

const originalRows: food[] = [
  { name: "Pizza", calories: 200, fat: 6.0, carbs: 24, protein: 4.0 },
  { name: "Hot Dog", calories: 300, fat: 6.0, carbs: 24, protein: 4.0 },
  { name: "Burger", calories: 400, fat: 6.0, carbs: 24, protein: 4.0 },
  { name: "Hamburger", calories: 500, fat: 6.0, carbs: 24, protein: 4.0 },
  { name: "Fries", calories: 600, fat: 6.0, carbs: 24, protein: 4.0 },
  { name: "Ice Cream", calories: 700, fat: 6.0, carbs: 24, protein: 4.0 }
];

Truthfully, this search example is acting more like a filter on the Material-UI Table than a search: starting with a dataset and filtering out results that don’t match the criteria. Lazy loading, discussed later in this article, acts more like a real search: passing an option and querying the database to get the desired data. However, the lines between search and filter are blurry. They are a UI presentation question as much as a data question.

Material-Table for React Table Search Example

If you want a Material-UI Table with tons of built in functionality, take a look at material-table for React. Material-Table has tons of features that you wish came out-of-the-box with Material-UI’s Table component. It is built on top of Material-UI, so you still have the same look, feel, and functionality.

A search bar is as easy to implement as a simple boolean:

import MaterialTable from 'material-table';

<MaterialTable
    options={{
      search: true
    }}
/>

And the result is this handy feature at the top right corner of your table component:

MUI Table search component UI
MUI Table search component UI

Material-UI-Filter Table Filter Example

Material-UI-Filter has good docs and a great live demo. However, it hasn’t been updated since late 2019 (as of writing this article). Here’s a quick list of pros and cons…remember, this is only my opinion after playing with it some. You may have a better experience if you really get into the details with it.

Pros:

  • The docs and demo are really good.
  • Beautiful and looks like a natural part of MUI.
  • Behaves exactly like a filter should – a Drawer pops out, filters are added on demand, etc.

Cons:

  • It doesn’t use hooks even though hooks existed at the time of its last update.
  • It uses Redux. This is likely fine for most people. However, it could probably have worked simply using React hooks and been more flexible.
  • I had difficulty getting it working. There were quite a few dependencies to download.

Filter-Material-UI Table Filter Example

Clearly Filter-Material-UI was released after Material-UI-Filter and the good name was taken ;). This library is newer and much easier to get working. However…it is not nearly as slickly styled. It doesn’t ‘feel’ like Material-UI in my opinion.

I quickly got it running in my app using the default categories from the demo (not the data in my table). The layout is built using Material-UI Grid. If you were determined to change the styling, you could probably do so (to some extent) by giving <FilterMaterialUI /> a class and then targeting the global classes API of the Select components nested inside.

Material-UI Table Filter library
Material-UI Table Filter library

My opinion below:

Pros

  • Very quick to get working.
  • Recently updated.
  • The component itself is simple and relies on a ‘fields‘ prop for its data structure. This reminds me of Columns in Material-UI.

Cons

  • Probably a challenge to style.
  • It would be nice to add and remove unwanted filter fields.
  • The UI look doesn’t seem as slick as Material-UI-Filter.

Material-Table For React Table Filter Example

Material-Table is a completely new table component with lots of options. However, you are not directly using MUI’s Table component.

If you use Material-Table, adding filtering requires only one additional line of code. Here’s a full example:

<MaterialTable
  columns={[
    {
      title: "Name",
      field: "name"
    },
    { title: "Occupation", field: "job" },
    { title: "Age", field: "age", type: "numeric" }
  ]}
  data={data}
  title="Material-Table Demo"
  options={{
    filtering: true
  }}
/>

Here’s a screenshot example of filtering in Material-Table:

MUI Table Filter Example
MUI Table Filter Example

Material-Table supports MUI v5 and v4.

Lazy Loading an MUI Table With Search?

Lazy loading allows the browser to render only a small subset of the total data in a data heavy component.

My example above used local data for demonstration purposes. However, most of the time a table will be rendering data fetched from a “backend” or API of some kind. If this data set contains hundreds or thousands of rows, ideally you want to have the backend handle the data querying and only return precisely the data the UI needs to display at that moment.

To accomplish this, pass the following three parameters in the request:

  • page number
  • batch size
  • search value

And simply make the backend request from the onChange handler (which we called requestSearch above) instead of performing a local filter. If network latency is too slow to allow requests with every change, consider only firing requests with the onRequestSearch event. This event is only fired when the search icon is actually clicked.

If the backend is not willing or able to accept the page number, batch size, and search value params, then local “lazy loading” can still reduce render times by reducing the amount of rows rendered at any given time. You have to filter the array of data on the FE instead, similar to the requestSearch function above.

Another option for large datasets is the DataGrid component. It is optimized for pagination or infinite scroll, lazy loading, and efficiently rendering data.

Resources

My MUI course on Udemy is now available!!! Build a full MUI app from beginning to end, learn every aspect of the sx prop, styled API, and the theme, and tackle the most challenging components! Do you want an active Q&A with me?!? Check here for coupons for my MUI course on Udemy.

IF you want to build your own filter, step one is to get the Drawer to nest inside the div that wraps the Table. I wrote the code and how-to, which you can learn about here.

Code Sandbox Link

I also have a written dozens of articles about styling Material-UI on this site, including articles about Material-UI TextField and Grid components, as well as developing custom Material-UI Palette theming. My goal is to make demos of some of the trickiest styling and implementation details I have encountered while using Material-UI.

Share this post:

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.