8
votes

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

3
Seems to work fine with the example output you posted. You can check it out here: wdre6.csb.app. The problem probably lies within your resolved data. - Isaac Pak
@IsaacPak Yes, I see it is working there (wdre6.csb.app) Do you have any suggestions what the issue could be with the resolved data, how to debug and solve the issue? - tw1742
data: result._embedded.publications vs data: result.data._embedded.publications - Isaac Pak
you can play around with it here: codesandbox.io/s/search-remote-data-wdre6 - Isaac Pak

3 Answers

6
votes

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.

5
votes

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;
0
votes

If you want to search inside all the rows and columns of the table, you can use the following function.

resolve({
           data: result._embedded.publications.filter(function(obj) {
          return Object.keys(obj).some(function(key) {
            return obj[key] ? (obj[key]).toString().includes(query.search) : false;
          })
        }),
           page: result.page.number,
           totalCount: result.page.totalElements,
     })

remoteSearch=(arr, searchKey)=>{
    return arr.filter(function(obj) {
      return Object.keys(obj).some(function(key) {
        return obj[key] ? (obj[key]).toString().includes(searchKey) : false;
      })
    });
  }
  
  
  console.log(remoteSearch([{a:1},{b:"1"},{c:"test1"}],1))