7

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
      }}
    />
  );
}
usersina
  • 1,063
  • 11
  • 28

1 Answers1

2

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

5eb
  • 14,798
  • 5
  • 21
  • 65
  • Nice trick! However, there are 2 minors issues in the example: 1-Column hover is triggered when the button is hovered. 2-The column text is slightly above the sort arrow. – usersina Jan 23 '21 at 10:10
  • 1
    @AnisBenna I've updated by answer with, I think, a better approach. It should solve the issues you mentioned. – 5eb Jan 23 '21 at 17:11