react-pivottable

A React-based pivot table

Downloads in past

Stats

StarsIssuesVersionUpdatedCreatedSize
react-pivottable
9661010.11.03 years ago7 years agoMinified + gzip package size for react-pivottable in KB

Readme

react-pivottable
react-pivottable is a React-based pivot table library with drag'n'drop functionality. It is a React port of the jQuery-based PivotTable.js by the same author.
react-pivottable is part of Plotly's React Component Suite for building data visualization Web apps and products.

What does it do & where is the demo?

react-pivottable's function is to enable data exploration and analysis by summarizing a data set into table or Plotly.js chart with a true 2-d drag'n'drop UI, very similar to the one found in older versions of Microsoft Excel.
A live demo can be found here.
screencap

How can I use it in my project?

Drag'n'drop UI with Table output only

Installation is via NPM and has a peer dependency on React:
npm install --save react-pivottable react react-dom

Basic usage is as follows. Note that PivotTableUI is a "dumb component" that maintains essentially no state of its own.
import React from 'react';
import ReactDOM from 'react-dom';
import PivotTableUI from 'react-pivottable/PivotTableUI';
import 'react-pivottable/pivottable.css';

// see documentation for supported input formats
const data = [['attribute', 'attribute2'], ['value1', 'value2']];

class App extends React.Component {
    constructor(props) {
        super(props);
        this.state = props;
    }

    render() {
        return (
            <PivotTableUI
                data={data}
                onChange={s => this.setState(s)}
                {...this.state}
            />
        );
    }
}

ReactDOM.render(<App />, document.body);

Drag'n'drop UI with Plotly charts as well as Table output

The Plotly react-plotly.js component can be passed in via dependency injection. It has a peer dependency on plotly.js.
Important: If you build your project using webpack, you'll have to follow these instructions in order to successfully bundle plotly.js. See below for how to avoid having to bundle plotly.js.
npm install --save react-pivottable react-plotly.js plotly.js react react-dom

To add the Plotly renderers to your app, you can use the following pattern:
import React from 'react';
import PivotTableUI from 'react-pivottable/PivotTableUI';
import 'react-pivottable/pivottable.css';
import TableRenderers from 'react-pivottable/TableRenderers';
import Plot from 'react-plotly.js';
import createPlotlyRenderers from 'react-pivottable/PlotlyRenderers';

// create Plotly renderers via dependency injection
const PlotlyRenderers = createPlotlyRenderers(Plot);

// see documentation for supported input formats
const data = [['attribute', 'attribute2'], ['value1', 'value2']];

class App extends React.Component {
    constructor(props) {
        super(props);
        this.state = props;
    }

    render() {
        return (
            <PivotTableUI
                data={data}
                onChange={s => this.setState(s)}
                renderers={Object.assign({}, TableRenderers, PlotlyRenderers)}
                {...this.state}
            />
        );
    }
}

ReactDOM.render(<App />, document.body);

With external plotly.js

If you would rather not install and bundle plotly.js but rather get it into your app via something like <script> tag, you can ignore react-plotly.js' peer-dependcy warning and handle the dependency injection like this:
import React from 'react';
import PivotTableUI from 'react-pivottable/PivotTableUI';
import 'react-pivottable/pivottable.css';
import TableRenderers from 'react-pivottable/TableRenderers';
import createPlotlyComponent from 'react-plotly.js/factory';
import createPlotlyRenderers from 'react-pivottable/PlotlyRenderers';

// create Plotly React component via dependency injection
const Plot = createPlotlyComponent(window.Plotly);

// create Plotly renderers via dependency injection
const PlotlyRenderers = createPlotlyRenderers(Plot);

// see documentation for supported input formats
const data = [['attribute', 'attribute2'], ['value1', 'value2']];

class App extends React.Component {
    constructor(props) {
        super(props);
        this.state = props;
    }

    render() {
        return (
            <PivotTableUI
                data={data}
                onChange={s => this.setState(s)}
                renderers={Object.assign({}, TableRenderers, PlotlyRenderers)}
                {...this.state}
            />
        );
    }
}

ReactDOM.render(<App />, document.body);

Properties and layered architecture

  • <PivotTableUI {...props} />
<PivotTable {...props} />
* `<Renderer {...props} />`
  * `PivotData(props)`
The interactive component provided by react-pivottable is PivotTableUI, but output rendering is delegated to the non-interactive PivotTable component, which accepts a subset of its properties. PivotTable can be invoked directly and is useful for outputting non-interactive saved snapshots of PivotTableUI configurations. PivotTable in turn delegates to a specific renderer component, such as the default TableRenderer, which accepts a subset of the same properties. Finally, most renderers will create non-React PivotData object to handle the actual computations, which also accepts a subset of the same props as the rest of the stack.
Here is a table of the properties accepted by this stack, including an indication of which layer consumes each, from the bottom up:
| Layer | Key & Type | Default Value | Description | | -------------- | ------------------------------------------------ | ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | PivotData | data
see below for formats | (none, required) | data to be summarized | | PivotData | rows
array of strings | [] | attribute names to prepopulate in row area | | PivotData | cols
array of strings | [] | attribute names to prepopulate in cols area | | PivotData | vals
array of strings | [] | attribute names used as arguments to aggregator (gets passed to aggregator generating function) | | PivotData | aggregators
object of functions | aggregators from Utilites | dictionary of generators for aggregation functions in dropdown (see original PivotTable.js documentation
) | | PivotData | aggregatorName
string | first key in aggregators | key to aggregators object specifying the aggregator to use for computations | | PivotData | valueFilter
object of arrays of strings | {} | object whose keys are attribute names and values are objects of attribute value-boolean pairs which denote records to include or exclude from computation and rendering; used to prepopulate the filter menus that appear on double-click | | PivotData | sorters
object or function | {} | accessed or called with an attribute name and can return a function which can be used as an argument to array.sort for output purposes. If no function is returned, the default sorting mechanism is a built-in "natural sort" implementation. Useful for sorting attributes like month names, see original PivotTable.js example 1 and original PivotTable.js example 2. | | PivotData | rowOrder
string | "key_a_to_z" | the order in which row data is provided to the renderer, must be one of "key_a_to_z", "value_a_to_z", "value_z_to_a", ordering by value orders by row total | | PivotData | colOrder
string | "key_a_to_z" | the order in which column data is provided to the renderer, must be one of "key_a_to_z", "value_a_to_z", "value_z_to_a", ordering by value orders by column total | | PivotData | derivedAttributes
object of functions | {} | defines derived attributes (see original PivotTable.js documentation) | | Renderer | <any> | (none, optional) | Renderers may accept any additional properties | | PivotTable | renderers
object of functions | TableRenderers | dictionary of renderer components | | PivotTable | rendererName
string | first key in renderers | key to renderers object specifying the renderer to use | | PivotTableUI | onChange
function | (none, required) | function called every time anything changes in the UI, with the new value of the properties needed to render the new state. This function must be hooked into a state-management system in order for the "dumb" PivotTableUI component to work. | | PivotTableUI | hiddenAttributes
array of strings | [] | contains attribute names to omit from the UI | | PivotTableUI | hiddenFromAggregators
array of strings | [] | contains attribute names to omit from the aggregator arguments dropdowns | | PivotTableUI | hiddenFromDragDrop
array of strings | [] | contains attribute names to omit from the drag'n'drop portion of the UI | | PivotTableUI | menuLimit
integer | 500 | maximum number of values to list in the double-click menu | | PivotTableUI | unusedOrientationCutoff
integer | 85 | If the attributes' names' combined length in characters exceeds this value then the unused attributes area will be shown vertically to the left of the UI instead of horizontally above it. 0 therefore means 'always vertical', and Infinity means 'always horizontal'. |

Accepted formats for data

Arrays of objects

One object per record, the object's keys are the attribute names.
Note: missing attributes or attributes with a value of null are treated as if the value was the string "null".
const data = [
    {
        attr1: 'value1_attr1',
        attr2: 'value1_attr2',
        //...
    },
    {
        attr1: 'value2_attr1',
        attr2: 'value2_attr2',
        //...
    },
    //...
];

Arrays of arrays

One sub-array per record, the first sub-array contains the attribute names. If subsequent sub-arrays are shorter than the first one, the trailing values are treated as if they contained the string value "null". If subsequent sub-arrays are longer than the first one, excess values are ignored. This format is compatible with the output of CSV parsing libraries like PapaParse.
const data = [
    ['attr1', 'attr2'],
    ['value1_attr1', 'value1_attr2'],
    ['value2_attr1', 'value2_attr2'],
    //...
];

Functions that call back

The function will be called with a callback that takes an object as a parameter.
Note: missing attributes or attributes with a value of null are treated as if the value was the string "null".
const data = function(callback) {
    callback({
        "attr1": "value1_attr1",
        "attr2": "value1_attr2",
        //...
    });
    callback({
        "attr1": "value2_attr1",
        "attr2": "value2_attr2",
        //...
    };
    //...
};