0.1.2 • Published 4 years ago

react-datable v0.1.2

Weekly downloads
1
License
MIT
Repository
github
Last release
4 years ago

react-datable

react-datable is a lightweight, fast and extendable datagrid built for React

Table of Contents

Features

  • Lightweight
  • Fully customizable (JSX, templates, state, styles, callbacks)
  • Client-side & Server-side pagination
  • Multi-sort
  • Filters
  • Minimal design & easily themeable
  • Fully controllable via optional props and callbacks

demo

Demo react-datable

Basic

Demo react-datable

Custom cell

Demo react-datable

Custom Headers and accessor

Demo react-datable

Installation


npm i react-datable

usage

import React from "react";
import "./App.css";
import reactTable from "react-datable";

class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      headers: [
        {
          title: <button>id</button>,
          accessor: "id",
          index: 1,
          sortable: false,
          style: {
            textAlign: "center",
          },
          //dataType: "number",
        },
        { title: "#", accessor: "id", index: 2, dataType: "number" },
        {
          title: "First Name",
          accessor: "first_name",
          width: "200",
          index: 3,
          searchable: true,
          dataType: "string",
        },
        {
          title: "Last Name",
          searchable: true,
          accessor: (d) => d.last_name,
          width: "300",
          index: 4,
          dataType: "function",
        },
        {
          title: "username",
          // accessor: "username",
          accessor: (d) => (
            <span>
              name <i>{d.username}</i>
              <a href="#"> link</a>
            </span>
          ),
          width: "300",
          index: 5,
          searchable: true,
          dataType: "function",
        },
        {
          title: "rate",
          searchable: true,
          accessor: "doctor.average",

          width: "300",
          index: 6,
        },
        {
          title: "Rating",
          accessor: "doctor.avg_rate",
          searchable: false,
          index: 7,
          width: "200",
          cell: (row) => {
            return (
              <div className="rating">
                <div
                  style={{
                    backgroundColor: "lightskyblue",
                    textAlign: "center",
                    height: "1.9em",
                    width: (row.doctor.avg_rate / 5) * 201 + "px",
                    margin: "3px 0 4px 0",
                  }}
                >
                  <a href={`/showchart/${row.id}`}>{row.doctor.avg_rate}</a>
                </div>
              </div>
            );
          },
        },
      ],
      data: [],
      current_page: 1,
      last_page_url: null,
      next_page_url: null,
      per_page: 5,
      totalItemsCount: 5,
      from: null,
      to: null,
    };
  }

  onUpdateTable = (field, id, value) => {
    console.log(field, id, value);
    let data = this.state.data.slice();
    let updateRow = this.state.data.find((d) => {
      return d["id"] === id;
    });

    console.log("updateRow", updateRow);

    updateRow[field] = value;

    this.setState({
      edit: null,
      data: data,
    });
  };

  search = async (pageNumber = 1) => {
    try {
      let searchURL = `http://localhost:8000/api/search?page=${pageNumber}`;
      const response = await fetch(searchURL, {
        method: "POST",
        headers: {
          Accept: "application/json",
          "Content-Type": "application/json",
          "Access-Control-Allow-Origin": "*",
          "X-Requested-With": "XMLHttpRequest",
        },
      });
      const data = await response.json();
      if (data.error === false) {
        return data.data;
      } else {
        return {};
      }
    } catch (err) {
      console.error("error", err);
    }
  };
  async componentDidMount() {
    let res = await this.search();
    this.setState({
      data: res.data,
      current_page: res.current_page,
      last_page_url: res.last_page_url,
      next_page_url: res.next_page_url,
      per_page: res.per_page,
      totalItemsCount: res.total,
      from: res.from,
      to: res.to,
    });
  }

  /***
   * Handle Page Change
   */
  handlePageChange = async (pageNumber) => {
    let res = await this.search(pageNumber);
    this.setState({
      data: res.data,
      current_page: pageNumber,
    });
  };
  render() {
    const pagination = {
      enabled: true,
      itemsCountPerPage: this.state.per_page,
      position: ["bottom left", "top left"],
      pageRangeDisplayed: 5,
      onPageChange: this.handlePageChange,
      currentPage: this.state.current_page,
      prevPageText: "next",
      lastPageText: "last",
    };
    return (
      <div>
        <reactTable
          keyField="id"
          edit={true}
          pagination={pagination}
          width="100%"
          headers={this.state.headers}
          data={this.state.data}
          noData="No records!"
          onUpdate={this.onUpdateTable}
          totalItemsCount={this.state.totalItemsCount}
          //searchable
        />
      </div>
    );
  }
}
export default App;

react-datable Props

NameTypeDefaultDescription
keyFieldStringidPrimary key (used for edit data)
editBooleanfalseData can be modified or not
totalItemsCountNumberRequired. Total count of items which you are going to display
dataArrayArray Of Data
noDataArraytrueText of No records found
searchableBooleantrueData can be filtered or not
paginationObjectObject of the Pagination props
onUpdateFunctionItem data change handler when edited. Receive field, id, value as arg
widthString"100%"width of Table
headersArrayRequired. Table Headers an array of objects containing the following properties (See below)

Headers Props

NameTypeDefaultDescription
titleString / ReactElementRequired. Text of header (see Custom Title section for more details)
accessorBooleanfalseRequired. propertyName or Accessor eg. (row) => row.propertyName (see Accessors section for more details)
widthNumberRequired. width of Field
indexNumberRequired. This represents the position of the field in the table
cellObject Or Functioncustom property eg. cell: {type: "image",style: { width:"50px",}}(see Cells section for more details)
dataTypeStringRequired. Type of property Value
searchableNumberfalseproperty can be filtered or not
sortableNumberfalseproperty can be sorted or not

Accessors

Accessors are functions that return the value to populate the row's value for the column. This lets the render function not have to worry about accessing the correct data, the value is automatically populated in it's props.

If a string or array is passed the default accessor is used. The default accessor will parse the input into an array and recursively flatten it. Any values that contain a dot (.) will be split. This array is then used as the path to the value to return.

const headers = [
  {
    title: "#",
    accessor: "id",
    dataType: "number",
  },
  {
    title: "First Name",
    accessor: (row) => row.first_name,
    dataType: "function",
  },
  {
    title: "username",
    accessor: (row) => (
      <span>
        name <i>{row.username}</i>
        <a href="#"> link</a>
      </span>
    ),
    dataType: "function",
  },
  {
    title: "rate",
    accessor: "doctor.average",
  },
];

NOTE If your data has a field/key with a dot (.) you will need to supply a custom accessor.

Custom Cell And Title Rendering

You can use any react component or JSX to display content in column headers, and cells . Any component you use will be passed the following props (if available):

  • row - Original row from your data
  • index - The index of the row
// This column uses a stateless component to produce a different colored bar depending on the value
// You can also use stateful components or any other function that returns JSX
const headers = [
  {
    title: "avatar",
    accessor: "avatar",
    cell: {
      type: "image",
      style: {
        width: "50px",
      },
    },
  },
  {
    title: (
      <span>
        <i className="fa-tasks" /> Progress
      </span>
    ),
    accessor: "progress",
    cell: (row) => (
      <div
        style={{
          width: "100%",
          height: "100%",
          backgroundColor: "#dadada",
          borderRadius: "2px",
        }}
      >
        <div
          style={{
            width: `${row.value}%`,
            height: "100%",
            backgroundColor:
              row.value > 66
                ? "#85cc00"
                : row.value > 33
                ? "#ffbf00"
                : "#ff2e00",
            borderRadius: "2px",
            transition: "all .2s ease-out",
          }}
        />
      </div>
    ),
  },
];

Pagination Props

NameTypeDefaultDescription
enabledBooleantrueEnable or Disable pagination
positionArray"bottom left", "top left"Postion of pagination
onPageChangeFunctionRequired. Page change handler. Receive pageNumber as arg
currentPageNumber1Required. Active page
itemsCountPerPageNumber10Count of items per page
pageRangeDisplayedNumber5Range of pages in paginator, exclude navigation blocks (prev, next, first, last pages)
prevPageTextString / ReactElementText of prev page navigation button
firstPageTextString / ReactElement«Text of first page navigation button
lastPageTextString / ReactElement»Text of last page navigation button
nextPageTextString / ReactElementText of next page navigation button
getPageUrlFunctionGenerate href attribute for page
innerClassStringpaginationClass name of <ul> tag
activeClassStringactiveClass name of active <li> tag
activeLinkClassStringClass name of active <a> tag
itemClassStringDefault class of the <li> tag
itemClassFirstStringClass of the first <li> tag
itemClassPrevStringClass of the previous <li> tag
itemClassNextStringClass of the next <li> tag
itemClassLastStringClass of the last <li> tag
disabledClassStringdisabledClass name of the first, previous, next and last <li> tags when disabled
hideDisabledBooleanfalseHide navigation buttons (prev, next, first, last) if they are disabled.
hideNavigationBooleanfalseHide navigation buttons (prev page, next page)
hideFirstLastPagesBooleanfalseHide first/last navigation buttons
linkClassStringDefault class of the <a> tag
linkClassFirstStringClass of the first <a> tag
linkClassPrevStringClass of the previous <a> tag
linkClassNextStringClass of the next <a> tag
linkClassLastStringClass of the last <a> tag

Contributing

The people who contribute to react-datable do so for the love of open source, our users and ecosystem, and most importantly, pushing the web forward together.Developers like you can help by contributing to rich and vibrant documentation, issuing pull requests to help us cover niche use cases, and to help sustain what you love about react-datable. Anybody can help by doing any of the following: use react-datable in projects,Contribute to the core repository.

All pull requests are welcome !

Changelog

Please see CHANGELOG for more information what has changed recently.

License

react-datable uses the MIT license. See LICENSE for more details.