reactjsgridjs

Customize tablehead of react-gridjs


Intead of using the default search bar, I'd like to customize it as follows:

  1. Add a button in front of the search bar.
  2. Use an icon (<i className="fa fa-search"/>) in the search placeholder.

Image

Here's my code so far:

import { Grid, _ } from 'gridjs-react';

const tableColumns = [
  'Name',
  'Phone',
  {
    name: 'Custom component',
    formatter: (text) => _(<b>{text}</b>)
  }
]
const tableData = [
  ['John', 12345, 'myText1'],
  ['Mike', 67891, 'myText2'],
]

export default function myCustomGrid() {
  return (
    <Grid
      sort={true}
      search={true} // This adds the search inp
      columns={tableColumns}
      data={tableData}
      language={{
        search: {
          placeholder: '🔍 Search...'
        }
      }}
      pagination={{
        enabled: true,
        limit: 2
      }}
    />
  );
}

Solution

  • This might be a good use-case for a portal.

    This allows us to more flexibly decide where we render our button. Using portals we can make the button a sibbling of the search input:

    const gridjsHeadRoot = document.getElementsByClassName("gridjs-head");
    
    class GridHeaderButton extends React.Component {
      constructor(props) {
        super(props);
        this.el = document.createElement("button");
        this.el.innerText = "Click";
        this.el.style.cssText = `
          background-color: #0069d9;
          color: #fff; 
          border-radius: .25rem;
          padding: .375rem .75rem;
          float: right
        `;
        this.el.onclick = function () {
          // Do something
        };
      }
    
      componentDidMount() {
        gridjsHeadRoot[0].appendChild(this.el);
      }
    
      componentWillUnmount() {
        gridjsHeadRoot[0].removeChild(this.el);
      }
    
      render() {
        return ReactDOM.createPortal(this.props.children, this.el);
      }
    }
    

    Then you can use it like this:

    function MyCustomGrid() {
      return (
        <Grid
          sort={true}
          search={true} // This adds the search inp
          columns={tableColumns}
          data={tableData}
          language={{
            search: {
              placeholder: "🔍 Search...",
            },
          }}
          pagination={{
            enabled: true,
            limit: 2,
          }}
        />
      );
    }
    
    export default function App() {
      return (
        <div className="App">
          <MyCustomGrid />
          <GridHeaderButton />
        </div>
      );
    }
    

    The order of where you put GridHeaderButton is important here. Because GridHeaderButton targets an element rendered inside MyCustomGrid which means you should put GridHeaderButton below CustomGrid or it will not work.


    Sandbox Example