1 | # react-pivottable
|
2 |
|
3 | `react-pivottable` is a React-based pivot table library with drag'n'drop
|
4 | functionality. 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
|
12 | summarizing a data set into table or [Plotly.js](https://plot.ly/javascript/)
|
13 | chart with a true 2-d drag'n'drop UI, very similar to the one found in older
|
14 | versions of Microsoft Excel.
|
15 |
|
16 | A [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 |
|
24 | Installation is via NPM and has a peer dependency on React:
|
25 |
|
26 | ```
|
27 | npm install --save react-pivottable react react-dom
|
28 | ```
|
29 |
|
30 | Basic usage is as follows. Note that `PivotTableUI` is a "dumb component" that
|
31 | maintains essentially no state of its own.
|
32 |
|
33 | ```js
|
34 | import React from 'react';
|
35 | import PivotTableUI from 'react-pivottable/PivotTableUI';
|
36 | import 'react-pivottable/pivottable.css';
|
37 |
|
38 | // see documentation for supported input formats
|
39 | const data = [['attribute', 'attribute2'], ['value1', 'value2']];
|
40 |
|
41 | class 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 |
|
58 | ReactDOM.render(<App />, document.body);
|
59 | ```
|
60 |
|
61 | ### Drag'n'drop UI with Plotly charts as well as Table output
|
62 |
|
63 | The Plotly `react-plotly.js` component can be passed in via dependency
|
64 | injection. 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)
|
68 | in order to successfully bundle `plotly.js`. See below for how to avoid having
|
69 | to bundle `plotly.js`.
|
70 |
|
71 | ```
|
72 | npm install --save react-pivottable react-plotly.js plotly.js react react-dom
|
73 | ```
|
74 |
|
75 | To add the Plotly renderers to your app, you can use the following pattern:
|
76 |
|
77 | ```js
|
78 | import React from 'react';
|
79 | import PivotTableUI from 'react-pivottable/PivotTableUI';
|
80 | import 'react-pivottable/pivottable.css';
|
81 | import TableRenderers from 'react-pivottable/TableRenderers';
|
82 | import Plot from 'react-plotly.js';
|
83 | import createPlotlyRenderers from 'react-pivottable/PlotlyRenderers';
|
84 |
|
85 | // create Plotly renderers via dependency injection
|
86 | const PlotlyRenderers = createPlotlyRenderers(Plot);
|
87 |
|
88 | // see documentation for supported input formats
|
89 | const data = [['attribute', 'attribute2'], ['value1', 'value2']];
|
90 |
|
91 | class 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 |
|
109 | ReactDOM.render(<App />, document.body);
|
110 | ```
|
111 |
|
112 | #### With external `plotly.js`
|
113 |
|
114 | If you would rather not install and bundle `plotly.js` but rather get it into
|
115 | your app via something like `<script>` tag, you can ignore `react-plotly.js`'
|
116 | peer-dependcy warning and handle the dependency injection like this:
|
117 |
|
118 | ```js
|
119 | import React from 'react';
|
120 | import PivotTableUI from 'react-pivottable/PivotTableUI';
|
121 | import 'react-pivottable/pivottable.css';
|
122 | import TableRenderers from 'react-pivottable/TableRenderers';
|
123 | import createPlotlyComponent from 'react-plotly.js/factory';
|
124 | import createPlotlyRenderers from 'react-pivottable/PlotlyRenderers';
|
125 |
|
126 | // create Plotly React component via dependency injection
|
127 | const Plot = createPlotlyComponent(window.Plotly);
|
128 |
|
129 | // create Plotly renderers via dependency injection
|
130 | const PlotlyRenderers = createPlotlyRenderers(Plot);
|
131 |
|
132 | // see documentation for supported input formats
|
133 | const data = [['attribute', 'attribute2'], ['value1', 'value2']];
|
134 |
|
135 | class 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 |
|
153 | ReactDOM.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 |
|
163 | The interactive component provided by `react-pivottable` is `PivotTableUI`, but
|
164 | output rendering is delegated to the non-interactive `PivotTable` component,
|
165 | which accepts a subset of its properties. `PivotTable` can be invoked directly
|
166 | and is useful for outputting non-interactive saved snapshots of `PivotTableUI`
|
167 | configurations. `PivotTable` in turn delegates to a specific renderer component,
|
168 | such as the default `TableRenderer`, which accepts a subset of the same
|
169 | properties. Finally, most renderers will create non-React `PivotData` object to
|
170 | handle the actual computations, which also accepts a subset of the same props as
|
171 | the rest of the stack.
|
172 |
|
173 | Here is a table of the properties accepted by this stack, including an
|
174 | indication 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 |
|
203 | One 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
|
206 | if the value was the string `"null"`.
|
207 |
|
208 | ```js
|
209 | const 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 |
|
226 | One sub-array per record, the first sub-array contains the attribute names. If
|
227 | subsequent sub-arrays are shorter than the first one, the trailing values are
|
228 | treated as if they contained the string value `"null"`. If subsequent sub-arrays
|
229 | are longer than the first one, excess values are ignored. This format is
|
230 | compatible with the output of CSV parsing libraries like PapaParse.
|
231 |
|
232 | ```js
|
233 | const data = [
|
234 | ['attr1', 'attr2'],
|
235 | ['value1_attr1', 'value1_attr2'],
|
236 | ['value2_attr1', 'value2_attr2'],
|
237 | //...
|
238 | ];
|
239 | ```
|
240 |
|
241 | #### Functions that call back
|
242 |
|
243 | The 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
|
246 | if the value was the string `"null"`.
|
247 |
|
248 | ```js
|
249 | const 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 | ```
|