Skip to content

Headless Pivot

Use createPivotController when your application needs analytical results, exports or custom presentation without creating a revo-grid. The controller owns report execution and committed state; your app decides how to display the returned rows.

Interactive example

Execute Pivot without a grid

Refresh a real Pivot controller and inspect the returned result without any grid.

The example loads when visible.

This example renders the controller’s returned values in an ordinary HTML table. There is no RevoGrid element or grid plugin. Use Refresh to execute again, or select the source/query example to replace facts and filter the result.

Download the executable example into an application with Pivot installed and run:

Terminal window
node customer-example.mjs

It imports only @revolist/pivot/headless, prints real tables and asserts strict AVG, nonadditive totals, formulas, ranking, sorting, exports and refusal/recovery. No database or browser is needed. The downloadable example uses explicit V2 numeric policies for its advanced cases. The smaller starter below focuses on the controller lifecycle.

import { createPivotController, type PivotReport } from '@revolist/pivot/headless';
const report: PivotReport = {
kind: 'revogrid:pivot.report', version: 1,
fields: [
{ id: 'region', sourceProp: 'region' },
{ id: 'sales', sourceProp: 'sales' },
],
rows: ['region'], columns: [], filters: [],
measures: [{ id: 'total', fieldId: 'sales', aggregator: 'sum' }],
};
const controller = createPivotController({
report, source: [{ region: 'North', sales: 10 }, { region: 'North', sales: 5 }],
});
try {
const outcome = await controller.refresh();
if (outcome.status === 'failed') throw new Error(outcome.error.message);
console.table(controller.getSnapshot().view?.model.source); // North: 15
} finally {
controller.dispose();
}

Creation validates metadata synchronously and starts idle (autoLoad defaults to false). Catch validation exceptions as well as failed operation outcomes. During loading/failure, display the retained committed view and the pending/error state separately. Do not save a failed pending report as if it committed.

Read controller.getSnapshot() for the accepted view, loading state and errors. Subscribe when your app needs updates, and unsubscribe/dispose on teardown. replaceSource() replaces facts; replaceQuery() changes analytical query/window options. Report commands update layout and measures.

A headless controller may also bind a server adapter. Headless means the calculation is independent of grid rendering, not that it must run locally. Its aggregation execution pin must match the selected engine.

For grid installation return to Getting started; for controller limits, failure states and recovery see Execution and limits.

Headless reference · Calculated values · Report persistence.