Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Search not working with React material-table using remote data

I'm using the material-table module here [1] with remote data from a web service. I've included the search parameter, but it's not working and there are no error messages in the console.

Here is the code:

import React from 'react';
import ReactDOM from "react-dom";
import MaterialTable from 'material-table';


import { forwardRef } from 'react';

import AddBox from '@material-ui/icons/AddBox';
import ArrowUpward from '@material-ui/icons/ArrowUpward';
import Check from '@material-ui/icons/Check';
import ChevronLeft from '@material-ui/icons/ChevronLeft';
import ChevronRight from '@material-ui/icons/ChevronRight';
import Clear from '@material-ui/icons/Clear';
import DeleteOutline from '@material-ui/icons/DeleteOutline';
import Edit from '@material-ui/icons/Edit';
import FilterList from '@material-ui/icons/FilterList';
import FirstPage from '@material-ui/icons/FirstPage';
import LastPage from '@material-ui/icons/LastPage';
import Remove from '@material-ui/icons/Remove';
import SaveAlt from '@material-ui/icons/SaveAlt';
import Search from '@material-ui/icons/Search';
import ViewColumn from '@material-ui/icons/ViewColumn';

const tableIcons = {
    Add: forwardRef((props, ref) => <AddBox {...props} ref={ref} />),
    Check: forwardRef((props, ref) => <Check {...props} ref={ref} />),
    Clear: forwardRef((props, ref) => <Clear {...props} ref={ref} />),
    Delete: forwardRef((props, ref) => <DeleteOutline {...props} ref={ref} />),
    DetailPanel: forwardRef((props, ref) => <ChevronRight {...props} ref={ref} />),
    Edit: forwardRef((props, ref) => <Edit {...props} ref={ref} />),
    Export: forwardRef((props, ref) => <SaveAlt {...props} ref={ref} />),
    Filter: forwardRef((props, ref) => <FilterList {...props} ref={ref} />),
    FirstPage: forwardRef((props, ref) => <FirstPage {...props} ref={ref} />),
    LastPage: forwardRef((props, ref) => <LastPage {...props} ref={ref} />),
    NextPage: forwardRef((props, ref) => <ChevronRight {...props} ref={ref} />),
    PreviousPage: forwardRef((props, ref) => <ChevronLeft {...props} ref={ref} />),
    ResetSearch: forwardRef((props, ref) => <Clear {...props} ref={ref} />),
    Search: forwardRef((props, ref) => <Search {...props} ref={ref} />),
    SortArrow: forwardRef((props, ref) => <ArrowUpward {...props} ref={ref} />),
    ThirdStateCheck: forwardRef((props, ref) => <Remove {...props} ref={ref} />),
    ViewColumn: forwardRef((props, ref) => <ViewColumn {...props} ref={ref} />)
};

const GET_PUBLICATIONS_URL = 'http://193.62.54.159/backend/v1/publications?';


class App extends React.Component {

    render() {
        return (
            <MaterialTable
                icons={tableIcons}
                title="Remote Data Preview"
                columns={[
                    { title: 'Publication ID', field: 'publicationId' },
                    { title: 'PMID', field: 'pmid' },
                    { title: 'First author', field: 'firstAuthor' },
                    { title: 'Publication', field: 'title' },
                    { title: 'Journal', field: 'journal' },
                    { title: 'Status', field: 'status' },
                ]}
                data={query =>
                    new Promise((resolve, reject) => {
                        // let url = 'https://reqres.in/api/users?'
                        let url = GET_PUBLICATIONS_URL
                        url += 'size=' + query.pageSize
                        url += '&page=' + (query.page)
                        fetch(url)
                            .then(response => response.json())
                            .then(result => {
                                resolve({
                                    data: result._embedded.publications,
                                    page: result.page.number,
                                    totalCount: result.page.totalElements,
                                })
                            })
                    })
                }
                options={{
                    search: true
                }}
            />
        )
    }
}

// export default DemoMUITable_RemoteData;
ReactDOM.render(<App />, document.getElementById("root"));

Here is an example of the output from the web service call used above:

{
    _embedded: {
        publications: [{
                publicationId: "5d2dbec2483e4bcddc82c61c",
                pmid: "jqfWof0a6N",
                title: "hDoClFK1xW",
                journal: "bsmw70kDBz",
                firstAuthor: "NUed57buOd",
                publicationDate: "2019-07-16T12:07:01.937Z",
                correspondingAuthor: {
                    authorName: "VRbSDd72mC",
                    email: "YgH4UoELBp"
                },
                status: "ELIGIBLE",
                _links: {
                    self: {
                        href: "http://193.62.54.159/backend/v1/publications/5d2dbec2483e4bcddc82c61c?pmid=false"
                    }
                }
            },
            {
                publicationId: "5d2dbeff483e4bcddc82c61d",
                pmid: "WlQsCFYg3b",
                title: "bsthfcP7zY",
                journal: "sUULVFkYJQ",
                firstAuthor: "NUed57buOd",
                publicationDate: "2019-07-16T12:07:01.937Z",
                correspondingAuthor: {
                    authorName: "UOTBdYbsRh",
                    email: "ZUmHQ7evjl"
                },
                status: "ELIGIBLE",
                _links: {
                    self: {
                        href: "http://193.62.54.159/backend/v1/publications/5d2dbeff483e4bcddc82c61d?pmid=false"
                    }
                }
            },
            {
                publicationId: "5d2dbf05483e4bcddc82c61e",
                pmid: "V1KphgdwaG",
                title: "KoXVQJjoGp",
                journal: "1bO9QNNDCM",
                firstAuthor: "NUed57buOd",
                publicationDate: "2019-07-16T12:07:01.937Z",
                correspondingAuthor: {
                    authorName: "KsfpbpEAGc",
                    email: "p69YIXvYEq"
                },
                status: "ELIGIBLE",
                _links: {
                    self: {
                        href: "http://193.62.54.159/backend/v1/publications/5d2dbf05483e4bcddc82c61e?pmid=false"
                    }
                }
            },
            {
                publicationId: "5d2dbf0a483e4bcddc82c61f",
                pmid: "JEmARsAgWM",
                title: "CiOTlRIeD4",
                journal: "l1ofJObwtJ",
                firstAuthor: "NUed57buOd",
                publicationDate: "2019-07-16T12:07:01.937Z",
                correspondingAuthor: {
                    authorName: "rGdQGN5oPh",
                    email: "6PI3NfrnmV"
                },
                status: "ELIGIBLE",
                _links: {
                    self: {
                        href: "http://193.62.54.159/backend/v1/publications/5d2dbf0a483e4bcddc82c61f?pmid=false"
                    }
                }
            },
            {
                publicationId: "5d346e129bb39d8c6e33faa4",
                pmid: "cNUmFPonBy",
                title: "0LwQYP0fUK",
                journal: "C3gQOWPZ2C",
                firstAuthor: "q1LwUyYpgO",
                publicationDate: "2019-07-16T12:07:01.937Z",
                correspondingAuthor: {
                    authorName: "oJdt6ae7sp",
                    email: "jhdOF23b9m"
                },
                status: "ELIGIBLE",
                _links: {
                    self: {
                        href: "http://193.62.54.159/backend/v1/publications/5d346e129bb39d8c6e33faa4?pmid=false"
                    }
                }
            }
        ]
    },
    _links: {
        first: {
            href: "http://193.62.54.159/backend/v1/publications?page=0&size=5"
        },
        self: {
            href: "http://193.62.54.159/backend/v1/publications"
        },
        next: {
            href: "http://193.62.54.159/backend/v1/publications?page=1&size=5"
        },
        last: {
            href: "http://193.62.54.159/backend/v1/publications?page=5&size=5"
        }
    },
    page: {
        size: 5,
        totalElements: 26,
        totalPages: 6,
        number: 0
    }
}

Here are my app's dependencies:

"dependencies": {
    "@material-ui/icons": "^4.2.1",
    "material-table": "^1.40.1",
    "react": "^16.8.6",
    "react-dom": "^16.8.6",
    "react-scripts": "3.0.1"
  },

[1] https://github.com/mbrn/material-table

like image 273
tw1742 Avatar asked Jul 24 '19 15:07

tw1742


2 Answers

The query object contains a search field, which is the current search value. You have to pass that to your online query and filter it within the backend or filter it within the frontend like this:

 resolve({
       data: result._embedded.publications.filter(pub => pub.firstAuthor.contains(query.search)),
       page: result.page.number,
       totalCount: result.page.totalElements,
 })

if you filter it in the frontend, you should write your custom filter function to filter all relevant fields like name, id etc.

like image 160
Domino987 Avatar answered Nov 04 '22 04:11

Domino987


For anyone who came here looking for solution how to do server search in material-table using hooks.

There was a bug (https://github.com/mbrn/material-table/pull/1611 which was breaking search field, so make sure to have [email protected]

codesandbox.io/s/material-table-server-search-on-hooks-tnniz

import React, { useEffect, useState } from "react";
import MaterialTable from "material-table";
import useAxios from "axios-hooks";

const MaterialTableSearchDemo = () => {
  const [query, setQuery] = useState("");
  const [items, setItems] = useState([]);
  const [{ data = {}, loading }, runSearch] = useAxios(
    `https://api.github.com/search/repositories?q=${query}&sort=stars&order=desc&type=Repositories`,
    { manual: true }
  );

  const columns = [
    { title: "Name", field: "name" },
    { title: "Stars", field: "stargazers_count" }
  ];

  useEffect(() => {
    if (query) {
      runSearch();
    } else {
      setItems([]);
    }
  }, [query, runSearch]);

  useEffect(() => {
    if (!loading && Array.isArray(data.items)) {
      setItems(data.items);
    }
  }, [loading, setItems, data.items]);

  return (
    <MaterialTable
      title="Github repositories"
      data={items}
      columns={columns}
      onSearchChange={setQuery}
      options={{
        debounceInterval: 500,
        paging: false,
        //searchAutoFocus: true
      }}
      localization={{
        toolbar: {
          searchPlaceholder: "e.g. React"
        }
      }}
      isLoading={loading}
    />
  );
};

export default MaterialTableSearchDemo;
like image 43
keemor Avatar answered Nov 04 '22 05:11

keemor