npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

react-datable

v0.1.2

Published

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

Downloads

7

Readme

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

| Name | Type | Default | Description | | ----------------- | -------- | ------- | ----------------------------------------------------------------------------------------------- | | keyField | String | id | Primary key (used for edit data) | | edit | Boolean | false | Data can be modified or not | | totalItemsCount | Number | | Required. Total count of items which you are going to display | | data | Array | | Array Of Data | | noData | Array | true | Text of No records found | | searchable | Boolean | true | Data can be filtered or not | | pagination | Object | | Object of the Pagination props | | onUpdate | Function | | Item data change handler when edited. Receive field, id, value as arg | | width | String | "100%" | width of Table | | headers | Array | | Required. Table Headers an array of objects containing the following properties (See below) |

Headers Props

| Name | Type | Default | Description | | ------------ | --------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------- | | title | String / ReactElement | | Required. Text of header (see Custom Title section for more details) | | accessor | Boolean | false | Required. propertyName or Accessor eg. (row) => row.propertyName (see Accessors section for more details) | | width | Number | | Required. width of Field | | index | Number | | Required. This represents the position of the field in the table | | cell | Object Or Function | | custom property eg. cell: {type: "image",style: { width:"50px",}}(see Cells section for more details) | | dataType | String | | Required. Type of property Value | | searchable | Number | false | property can be filtered or not | | sortable | Number | false | property 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

| Name | Type | Default | Description | | -------------------- | --------------------- | --------------------------- | -------------------------------------------------------------------------------------- | | enabled | Boolean | true | Enable or Disable pagination | | position | Array | ["bottom left", "top left"] | Postion of pagination | | | onPageChange | Function | | Required. Page change handler. Receive pageNumber as arg | | currentPage | Number | 1 | Required. Active page | | itemsCountPerPage | Number | 10 | Count of items per page | | pageRangeDisplayed | Number | 5 | Range of pages in paginator, exclude navigation blocks (prev, next, first, last pages) | | prevPageText | String / ReactElement | | Text of prev page navigation button | | firstPageText | String / ReactElement | « | Text of first page navigation button | | lastPageText | String / ReactElement | » | Text of last page navigation button | | nextPageText | String / ReactElement | | Text of next page navigation button | | getPageUrl | Function | | Generate href attribute for page | | innerClass | String | pagination | Class name of <ul> tag | | activeClass | String | active | Class name of active <li> tag | | activeLinkClass | String | | Class name of active <a> tag | | itemClass | String | | Default class of the <li> tag | | itemClassFirst | String | | Class of the first <li> tag | | itemClassPrev | String | | Class of the previous <li> tag | | itemClassNext | String | | Class of the next <li> tag | | itemClassLast | String | | Class of the last <li> tag | | disabledClass | String | disabled | Class name of the first, previous, next and last <li> tags when disabled | | hideDisabled | Boolean | false | Hide navigation buttons (prev, next, first, last) if they are disabled. | | hideNavigation | Boolean | false | Hide navigation buttons (prev page, next page) | | hideFirstLastPages | Boolean | false | Hide first/last navigation buttons | | linkClass | String | | Default class of the <a> tag | | linkClassFirst | String | | Class of the first <a> tag | | linkClassPrev | String | | Class of the previous <a> tag | | linkClassNext | String | | Class of the next <a> tag | | linkClassLast | String | | Class 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.