UNPKG

22.4 kBMarkdownView Raw
1# react-pivottable
2
3`react-pivottable` is a React-based pivot table library with drag'n'drop
4functionality. It is a React port of the jQuery-based
5[PivotTable.js](https://pivottable.js.org/) by the same author.
6
7`react-pivottable` is part of Plotly's [React Component Suite](https://plot.ly/products/react/) for building data visualization Web apps and products.
8
9## What does it do & where is the demo?
10
11`react-pivottable`'s function is to enable data exploration and analysis by
12summarizing a data set into table or [Plotly.js](https://plot.ly/javascript/)
13chart with a true 2-d drag'n'drop UI, very similar to the one found in older
14versions of Microsoft Excel.
15
16A [live demo can be found here](https://react-pivottable.js.org/).
17
18![screencap](examples/basic.gif)
19
20## How can I use it in my project?
21
22### Drag'n'drop UI with Table output only
23
24Installation is via NPM and has a peer dependency on React:
25
26```
27npm install --save react-pivottable react react-dom
28```
29
30Basic usage is as follows. Note that `PivotTableUI` is a "dumb component" that
31maintains essentially no state of its own.
32
33```js
34import React from 'react';
35import PivotTableUI from 'react-pivottable/PivotTableUI';
36import 'react-pivottable/pivottable.css';
37
38// see documentation for supported input formats
39const data = [['attribute', 'attribute2'], ['value1', 'value2']];
40
41class App extends React.Component {
42 constructor(props) {
43 super(props);
44 this.state = props;
45 }
46
47 render() {
48 return (
49 <PivotTableUI
50 data={data}
51 onChange={s => this.setState(s)}
52 {...this.state}
53 />
54 );
55 }
56}
57
58ReactDOM.render(<App />, document.body);
59```
60
61### Drag'n'drop UI with Plotly charts as well as Table output
62
63The Plotly `react-plotly.js` component can be passed in via dependency
64injection. It has a peer dependency on `plotly.js`.
65
66**Important:** If you build your project using webpack, you'll have to follow
67[these instructions](https://github.com/plotly/plotly.js#building-plotlyjs-with-webpack)
68in order to successfully bundle `plotly.js`. See below for how to avoid having
69to bundle `plotly.js`.
70
71```
72npm install --save react-pivottable react-plotly.js plotly.js react react-dom
73```
74
75To add the Plotly renderers to your app, you can use the following pattern:
76
77```js
78import React from 'react';
79import PivotTableUI from 'react-pivottable/PivotTableUI';
80import 'react-pivottable/pivottable.css';
81import TableRenderers from 'react-pivottable/TableRenderers';
82import Plot from 'react-plotly.js';
83import createPlotlyRenderers from 'react-pivottable/PlotlyRenderers';
84
85// create Plotly renderers via dependency injection
86const PlotlyRenderers = createPlotlyRenderers(Plot);
87
88// see documentation for supported input formats
89const data = [['attribute', 'attribute2'], ['value1', 'value2']];
90
91class App extends React.Component {
92 constructor(props) {
93 super(props);
94 this.state = props;
95 }
96
97 render() {
98 return (
99 <PivotTableUI
100 data={data}
101 onChange={s => this.setState(s)}
102 renderers={Object.assign({}, TableRenderers, PlotlyRenderers)}
103 {...this.state}
104 />
105 );
106 }
107}
108
109ReactDOM.render(<App />, document.body);
110```
111
112#### With external `plotly.js`
113
114If you would rather not install and bundle `plotly.js` but rather get it into
115your app via something like `<script>` tag, you can ignore `react-plotly.js`'
116peer-dependcy warning and handle the dependency injection like this:
117
118```js
119import React from 'react';
120import PivotTableUI from 'react-pivottable/PivotTableUI';
121import 'react-pivottable/pivottable.css';
122import TableRenderers from 'react-pivottable/TableRenderers';
123import createPlotlyComponent from 'react-plotly.js/factory';
124import createPlotlyRenderers from 'react-pivottable/PlotlyRenderers';
125
126// create Plotly React component via dependency injection
127const Plot = createPlotlyComponent(window.Plotly);
128
129// create Plotly renderers via dependency injection
130const PlotlyRenderers = createPlotlyRenderers(Plot);
131
132// see documentation for supported input formats
133const data = [['attribute', 'attribute2'], ['value1', 'value2']];
134
135class App extends React.Component {
136 constructor(props) {
137 super(props);
138 this.state = props;
139 }
140
141 render() {
142 return (
143 <PivotTableUI
144 data={data}
145 onChange={s => this.setState(s)}
146 renderers={Object.assign({}, TableRenderers, PlotlyRenderers)}
147 {...this.state}
148 />
149 );
150 }
151}
152
153ReactDOM.render(<App />, document.body);
154```
155
156## Properties and layered architecture
157
158* `<PivotTableUI {...props} />`
159 * `<PivotTable {...props} />`
160 * `<Renderer {...props} />`
161 * `PivotData(props)`
162
163The interactive component provided by `react-pivottable` is `PivotTableUI`, but
164output rendering is delegated to the non-interactive `PivotTable` component,
165which accepts a subset of its properties. `PivotTable` can be invoked directly
166and is useful for outputting non-interactive saved snapshots of `PivotTableUI`
167configurations. `PivotTable` in turn delegates to a specific renderer component,
168such as the default `TableRenderer`, which accepts a subset of the same
169properties. Finally, most renderers will create non-React `PivotData` object to
170handle the actual computations, which also accepts a subset of the same props as
171the rest of the stack.
172
173Here is a table of the properties accepted by this stack, including an
174indication of which layer consumes each, from the bottom up:
175
176| Layer | Key & Type | Default Value | Description |
177| -------------- | ------------------------------------------------ | ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
178| `PivotData` | `data` <br /> see below for formats | (none, required) | data to be summarized |
179| `PivotData` | `rows` <br /> array of strings | `[]` | attribute names to prepopulate in row area |
180| `PivotData` | `cols` <br /> array of strings | `[]` | attribute names to prepopulate in cols area |
181| `PivotData` | `vals` <br /> array of strings | `[]` | attribute names used as arguments to aggregator (gets passed to aggregator generating function) |
182| `PivotData` | `aggregators` <br /> object of functions | `aggregators` from `Utilites` | dictionary of generators for aggregation functions in dropdown (see [original PivotTable.js documentation](https://github.com/nicolaskruchten/pivottable/wiki/Aggregators)) |
183| `PivotData` | `aggregatorName` <br /> string | first key in `aggregators` | key to `aggregators` object specifying the aggregator to use for computations |
184| `PivotData` | `valueFilter` <br /> object of arrays of strings | `{}` | object whose keys are attribute names and values are arrays of attribute values which denote records to exclude from computation and rendering; used to prepopulate the filter menus that appear on double-click |
185| `PivotData` | `sorters` <br /> 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`](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/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](http://nicolas.kruchten.com/pivottable/examples/mps_agg.html) and [original PivotTable.js example 2](http://nicolas.kruchten.com/pivottable/examples/montreal_2014.html). |
186| `PivotData` | `rowOrder` <br /> 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 |
187| `PivotData` | `colOrder` <br /> 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 |
188| `PivotData` | `derivedAttributes` <br /> object of functions | `{}` | defines derived attributes (see [original PivotTable.js documentation](https://github.com/nicolaskruchten/pivottable/wiki/Derived-Attributes)) |
189| `Renderer` | `<any>` | (none, optional) | Renderers may accept any additional properties |
190| `PivotTable` | `renderers` <br /> object of functions | `TableRenderers` | dictionary of renderer components |
191| `PivotTable` | `rendererName` <br /> string | first key in `renderers` | key to `renderers` object specifying the renderer to use |
192| `PivotTableUI` | `onChange` <br /> 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. |
193| `PivotTableUI` | `hiddenAttributes` <br /> array of strings | `[]` | contains attribute names to omit from the UI |
194| `PivotTableUI` | `hiddenFromAggregators` <br /> array of strings | `[]` | contains attribute names to omit from the aggregator arguments dropdowns |
195| `PivotTableUI` | `hiddenFromDragDrop` <br /> array of strings | `[]` | contains attribute names to omit from the drag'n'drop portion of the UI |
196| `PivotTableUI` | `menuLimit` <br /> integer | 500 | maximum number of values to list in the double-click menu |
197| `PivotTableUI` | `unusedOrientationCutoff` <br /> 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'. |
198
199### Accepted formats for `data`
200
201#### Arrays of objects
202
203One object per record, the object's keys are the attribute names.
204
205_Note_: missing attributes or attributes with a value of `null` are treated as
206if the value was the string `"null"`.
207
208```js
209const data = [
210 {
211 attr1: 'value1_attr1',
212 attr2: 'value1_attr2',
213 //...
214 },
215 {
216 attr1: 'value2_attr1',
217 attr2: 'value2_attr2',
218 //...
219 },
220 //...
221];
222```
223
224#### Arrays of arrays
225
226One sub-array per record, the first sub-array contains the attribute names. If
227subsequent sub-arrays are shorter than the first one, the trailing values are
228treated as if they contained the string value `"null"`. If subsequent sub-arrays
229are longer than the first one, excess values are ignored. This format is
230compatible with the output of CSV parsing libraries like PapaParse.
231
232```js
233const data = [
234 ['attr1', 'attr2'],
235 ['value1_attr1', 'value1_attr2'],
236 ['value2_attr1', 'value2_attr2'],
237 //...
238];
239```
240
241#### Functions that call back
242
243The function will be called with a callback that takes an object as a parameter.
244
245_Note_: missing attributes or attributes with a value of `null` are treated as
246if the value was the string `"null"`.
247
248```js
249const data = function(callback) {
250 callback({
251 "attr1": "value1_attr1",
252 "attr2": "value1_attr2",
253 //...
254 });
255 callback({
256 "attr1": "value2_attr1",
257 "attr2": "value2_attr2",
258 //...
259 };
260 //...
261};
262```