The Easiest Way to Implement Material-UI Table Search and Filter

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. Not to worry, the React community has stepped up and provided several Material-UI search bar examples and solutions, two of which I will discuss in this article.

Material-UI Table with search

Likewise, there is no filter by default, and so I took a look at two 3rd party libraries for filtering. One of them has a slick UI in the demo, but the other is easier to implement. I’m going to go ahead and give you my opinion here though: you are likely better off developing your own simple filtering solution.

Code Sandbox link with full React code is in the Resources section.

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

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

Search Option 1: Material-UI-Search-Bar Library

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.

Search Option 2: Material-Table for React

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:

Table search component UI

Filter Option 1: Material-UI-Filter

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 Option 2: Filter-Material-UI

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

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.

What About Lazy Loading 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

Are you looking for video-based training in Material-UI? Check out my review of the best Material-UI course in Udemy, which has 40+ hours of content and a 30-day money back guarantee.

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.

Here’s everything you need to know about Material-UI Table Pagination.

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.