Pivoting with Infinite
An enteprise-level feature
InfiniteTable provides is the pivoting functionality. Combined with grouping and advanced aggregation, it unlocks new ways to visualize data.Pivoting is first defined at the
DataSource level, via the pivotBy prop. It's an array of objects, each with a field property bound (so pivotBy[].field is keyof DATA_TYPE) to the DataSource.Pivoting generates columns based on the pivoting values, so you have to pass those generated columns into the
<InfiniteTable /> component.You do that by using a
function as a direct child of the DataSource, and in that function you have access to the generated pivotColumns array. Likewise for pivotColumnGroups.For more pivoting examples, see our pivoting demos
#
Pivoting with avg aggregation
loading demo…
Sorting the group column and pivot columns#
Sorting the group column in a pivot table uses the same
sortInfo as in row grouping. For a single group column it is enough to pass { id: 'group-by', dir: 1 }. Based on the current groupByand your columns, it will detect the fields and the sorting it needs to apply.Generated pivot columns inherit sortability from the original
columns bound to the aggregation field — including columnDefaultSortable. You can override that with defaultSortable on the pivotColumn prop on <InfiniteTable />:That applies defaultSortable to every generated pivot column. The sort type is taken from the original
columns bound to the aggregation field.For narrower control — only one aggregation, or only columns in a specific pivot group — see customizing pivot columns.
Passing
defaultSortInfo as an array enables multiple sorting. Combined with multiSortBehavior="append", clicking a pivot column adds that sort instead of replacing the group-column sort.#
Pivoting with initial group-column sort and sortable leaf pivot columns
This table starts sorted by the group column (
preferredLanguage, then stack). Click a pivot column header — for example a yes or no column under a country — to add a sort by that aggregated value.loading demo…
Customizing Pivot Columns#
There are a number of ways to customize the pivot columns and pivot column groups. This is something you generally want to do, as they are generated and you might need to tweak column headers, size, etc. The three override points -
pivotColumn, pivotBy.column, and aggregationReducers.pivotColumn — are documented in customizing pivot columns.The default behavior for pivot columns generated for aggregations is that they inherit the properties of the original columns bound to the same field as the aggregation.
#
Pivot columns inherit from original columns bound to the same field
loading demo…
Another way to do it is to specify
pivotBy.column, as either an object, or (more importantly) as a function.
If you pass an object, it will be applied to all pivot columns in the column group generated for the field property.In the above example, the
column.defaultWidth=400 will be applied to columns generated for all canDesign values corresponding to each country. This is good but not good enough as you might want to customize the pivot column for every value in the pivot. You can do that by passing a function to the pivotBy.column property.#
Pivoting with customized pivot column
loading demo…
Total and grand-total columns#
In pivot mode you can configure both total columns and grand-total columns. By default, grand-total columns are not displayed, so you have to explicitly set the
pivotGrandTotalColumnPosition prop for them to be visible.Pivot total columns are only displayed when pivotBy has two or more fields (
pivotBy.length > 1). With a single pivot field only grand-total columns can be shown, and naving pivotTotalColumnPosition has no effect — the totals would be the same as the already displayed values.The example below pivots by
stack and canDesign so both total and grand-total columns are visible.#
Pivoting with customized position for totals and grand-total columns
loading demo…
What are grand-total columns?
For each aggregation reducer specified in the
DataSource, you can have a total column - this is what grand-total columns basically are.Server-side pivoting#
By default, pivoting is client side. However, if you specify
DataSource.lazyLoad and provide a function that returns a promise for the DataSource.data prop, the table will use server-pivoted data.The
DataSource.data function is expected to return a promise that resolves to an object with the following shape:totalCount- the total number of records in the group we're pivoting ondata- an array of objects that describes child groups, each object has the following properties:keys- an array of the group keys (usually strings) that uniquely identifies the group, from the root to the current groupdata- an object that describes the common properties of the groupaggregations- an object that describes the aggregations for the current grouppivot- the pivoted values and aggregations for each value. This object will have the following properties:totals- an object with a key for each aggregation. The value is the aggregated value for the respective aggregation reducer.values- an object keyed with the unique values for the pivot field. The values of those keys are objects with the same shape as thepivottop-level object, namelytotalsandvalues.
In the example below, let's assume the following practical scenario, with the data-type being a
Developer{country, stack, preferredLanguage, canDesign, age, salary}.#
Server-side pivoting example
loading demo…
The
groupRenderStrategy prop is applicable even to pivoted tables, but groupRenderStrategy="inline" is not supported in this case.Another pivoting example with batching#
Pivoting builds on the same data response as server-side grouping, but adds the pivot values for each group, as we already showed. Another difference is that in pivoting, no leaf rows are rendered or loaded, since this is pivoting and it only works with aggregated data. This means the
DataSource.data function must always return the same format for the response data.Just like server-side grouping, server-side pivoting also supports batching - make sure you specify
lazyLoad.batchSize.The example below also shows you how to customize the table rows while records are still loading.
#
Server side pivoting with lazy loding batching
loading demo…
Here's another example, that assumes grouping by
country and city, aggregations by age and salary (average values) and pivot by preferredLanguage and canDesign (a boolean property):If we were to scroll down, the next batch of data would have the same structure as the previous one, but with
lazyLoadStartIndex set to 10 (if lazyLoad.batchSize = 10).Now let's expand the first group and see how the request/response would look like:
The response can contain a
mappings key with values for totals and values keys - this can be useful for making the server-side pivot response lighter.If
mappings would be {totals: "t", values: "v"}, the response would look like this:More-over, you can also give aggregationReducers shorter keys to make the server response even more compact
Adding a
cache: true key to the resolved object in the DataSource.data call will cache the value for the expanded group, so that when collaped and expanded again, the cached value will be used, and no new call is made to the DataSource.data function. This is applicable for both pivoted and/or grouped data. Not passing cache: true will make the function call each time the group is expanded.