Skip to content

Headless API and Persistence

PivotChartsPlugin is the source of truth for chart data and lifecycle. PivotChartsUiPlugin is a client of that API; applications can build their own gallery, settings, containers, or workspace without replacing the data model.

For normal application-owned charts, use mountPivotChart():

import { mountPivotChart } from '@revolist/revogrid-enterprise';
const chart = await mountPivotChart(grid, {
container: document.querySelector<HTMLElement>('#dashboard-chart')!,
});

The container does not need to be inside the grid. The default controls: 'none' path renders only the chart and requires no UI plugin. Request controls: 'standard' when the same container should include the built-in configuration experience:

const chart = await mountPivotChart(grid, {
container: document.querySelector<HTMLElement>('#chart-workspace')!,
controls: 'standard',
});

controls: 'standard' requires PivotChartsUiPlugin; chart-only mounting does not. Both return the same PivotChartRef. Give the mount container an explicit height. The built-in renderer fills the available size and observes later layout changes, including a mounted container that becomes visible later. Treat the container as an empty chart mount point: mounting replaces its children, and chart.destroy() leaves it empty.

Configuration controls are optional application UI. Each control can call the same chart ref without recreating the renderer:

chartTypeSelect.addEventListener('change', async () => {
await chart.update({
chartType: chartTypeSelect.value as PivotChartType,
});
});
dataLabelsCheckbox.addEventListener('change', async () => {
await chart.update({
presentation: { dataLabels: dataLabelsCheckbox.checked },
});
});

See the Pivot Charts overview for complete minimal markup and setup for chart-only, standard-control, and component-lifecycle integrations.

Use the plugin instance when an advanced workflow needs collection-wide methods such as restore, getChartModels(), or destroyAllCharts():

const charts = (await grid.getPlugins()).find(
(plugin) => plugin instanceof PivotChartsPlugin,
) as PivotChartsPlugin;
MethodPurpose
getChartData(options?)Project and validate a cached immutable dataset for the current Pivot revision and optional semantic scope.
createChart(params)Create a model, resolve data, mount a renderer instance, and return PivotChartRef.
updateChart(chartId, patch)Validate and queue a model/data/presentation update.
refreshChart(chartId)Reproject a linked chart from the current committed Pivot.
canDrillDown(chartId, target)Test a semantic row, column, or two-axis drill target.
drillDownChart(chartId, target)Load and commit a child frame.
drillUpChart(chartId)Navigate to the parent frame.
drillToChart(chartId, frameIndex)Jump to a stored breadcrumb frame.
resetChartDrill(chartId)Return to the chart’s root frame.
retryChartDrill(chartId)Retry the last failed drill transition.
getChartModels()Return cloned serializable models for every active chart.
restoreChart(model, options)Validate a saved model and recreate it in a supplied container.
downloadChart(chartId, options?)Delegate an advertised PNG/PDF download to the renderer.
getChartImageDataURL(chartId, options?)Request an image data URL from a capable renderer.
destroyChart(chartId)Destroy one renderer and release its state.
destroyAllCharts()Destroy every chart owned by the plugin.

All updates for a chart are serialized. A later linked refresh cannot partially overwrite an earlier options update.

const chart = await charts.createChart({
container: document.querySelector('#sales-chart')!,
chartType: 'groupedColumn',
linked: true,
totals: 'none',
bindings: {},
initialScope: {
rowPath: ['Europe'],
rowLabels: ['Europe'],
columnPath: [2026],
columnLabels: ['2026'],
},
presentation: {
title: 'European sales',
legendPosition: 'bottom',
},
theme: 'auto',
chartOptions: {
showGridLines: true,
markOpacity: 0.9,
},
drillSyncMode: 'chart',
});
await chart.update({
chartType: 'stackedColumn',
totals: 'grand',
presentation: { subtitle: 'Including grand total' },
});

Data-affecting patches reproject or validate a snapshot. Presentation, theme, and chart-option changes reuse the current dataset. Failed renderer updates roll back to the previous model and rendered input.

The ref scopes common operations to one chart:

chart.id;
chart.container;
chart.model;
await chart.update({ linked: false });
chart.canDrillDown({ axis: 'row', category });
await chart.drillDown({ axis: 'row', category });
await chart.drillUp();
await chart.drillTo(0);
await chart.resetDrill();
await chart.retryDrill();
chart.getDrillState();
chart.focus();
chart.destroy();

model and getDrillState() return clones. Mutating them does not update the active chart; call update or a drill method.

PivotChartModel version 2 contains:

  • stable chartId and chartType;
  • link state and an optional unlinked dataset snapshot;
  • totals, series selection, values-on-rows measure, and semantic bindings;
  • presentation, renderer theme, and validated chart options;
  • breadcrumb/drill scope and drill synchronization mode.
const saved = charts.getChartModels();
localStorage.setItem('pivot-charts', JSON.stringify(saved));
const restoredModels = JSON.parse(
localStorage.getItem('pivot-charts') ?? '[]',
);
for (const model of restoredModels) {
await charts.restoreChart(model, {
container: createWorkspacePanel(model.chartId),
});
}

Restore parses the current model version, checks chart identity, renderer support, options, bindings, selected series, hierarchy paths, dataset shape, limits, and linked/unlinked rules. Older model versions are rejected rather than implicitly migrated. Supply chartId in PivotChartRestoreOptions only when the application intentionally replaces the persisted identity.

const renderer: PivotChartRenderer = {
capabilities: {
supportedTypes: ['groupedColumn', 'line'],
download: true,
downloadFormats: ['png'],
imageDataUrl: true,
},
create(input) {
const instance = mountApplicationChart(input);
return {
update(nextInput) {
instance.update(nextInput);
},
focus() {
instance.focus();
},
async download(options) {
await instance.downloadPng(options);
},
async getImageDataURL(options) {
return instance.getPngDataUrl(options);
},
destroy() {
instance.destroy();
},
};
},
};

PivotChartRenderInput contains the chart ID, container, chart type, validated dataset, bindings, presentation, chart options, theme, locale text, chart/preview render mode, and the semantic node-click callback. A custom renderer must not mutate the supplied dataset or model state.

The UI gallery exposes only capabilities.supportedTypes. Download and image actions are available only when the renderer advertises and implements them.

PivotChartsUiPlugin.openChart(params) accepts every PivotChartCreateParams field except container; the UI owns its chart container. pivotChartsUi.dialogParent can move the modeless host into an application overlay root. Closing the dialog destroys its chart.

PivotChartsUiPlugin.mountChart(params) is the lower-level equivalent of mountPivotChart(..., { controls: 'standard' }). It embeds the existing gallery, Data, Customize, current-frame table, export, and drill controls in the supplied application container. Prefer mountPivotChart() unless the UI plugin instance is already part of a larger plugin-management workflow.

EventDetail
pivot-chart-createdChart ID and PivotChartRef.
pivot-chart-updatedChart ID, update reason, and cloned model.
pivot-chart-destroyedChart ID.
pivot-chart-node-clickSemantic category/series, paths, measure, and aggregator.
pivot-chart-errorOptional chart ID and normalized Error.
pivot-chart-before-drillCancelable transition with from/to drill state.
pivot-chart-drill-startPending drill transition.
pivot-chart-drilledSuccessful transition with model and dataset.
pivot-chart-drill-errorFailed transition and error.
pivot-chart-drill-resetSuccessful reset transition.
pivot-chart-drill-syncSynchronization request and selected mode.

Update reasons are data, options, theme, relink, and drill.

Previous: Customization and export · Next: Server data and performance · API reference