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/pivot';
const chart = await mountPivotChart(grid, { container: document.querySelector<HTMLElement>('#dashboard-chart')!,});Application-owned containers
Section titled “Application-owned containers”Application-owned charts
Compare a linked chart with a frozen snapshot as the Pivot changes, then relink it.
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.
Direct plugin access
Section titled “Direct plugin access”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;Plugin methods
Section titled “Plugin methods”| Method | Purpose |
|---|---|
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. |
setChartSelection(chartId, selection) | Commit owned semantic selection and apply Filter-mode predicates. |
clearChartSelection(chartId) | Clear selection and release only this chart’s filter contribution. |
requestChartSelectionClear(chartId, origin?) | Handle a custom UI clear action: request an empty selection in Event mode, or commit clearing in other modes. |
getChartRendererCapabilities(chartId) | Inspect the creation-time backend’s supported types, interaction modes, options, and graphics features. |
getChartRenderer(chartId) | Obtain the creation-time renderer factory for matching previews or other advanced integrations. |
getChartDownloadCapabilities(chartId) | Discover CSV and the existing renderer instance’s graphics formats and PDF encoding. |
getChartCSV(chartId, options?) | Encode committed chart data without downloading or loading a provider. |
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?) | Download advertised PNG/SVG/PDF graphics or plugin-owned chart-data CSV. |
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.
Create and update
Section titled “Create and 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.
Patch values are owned before entering the chart’s queue. Omitted properties
preserve their current value. presentation merges its supplied fields; axes,
bindings, chart options, query, navigation, viewport, colors, annotations, and
series overrides replace their authored objects. Pass {} to reset those
objects. selection replaces the selection array, and seriesIds: [] selects
all configured series where the chart supports them. Changing chart type clears
chart options unless the same patch supplies options for the new type.
Render-only changes, including axes, viewport, presentation, and theme, preserve pending fresh data and drill caches. When that refresh completes, the chart uses the fresh data with its latest render settings. A source-changing query deliberately supersedes earlier source work; if the new operation fails, the previous committed chart remains available.
PivotChartRef
Section titled “PivotChartRef”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();await chart.setSelection(selection);await chart.clearSelection();chart.focus();chart.destroy();model and getDrillState() return clones. Mutating them does not update the
active chart; call update or a drill method.
Model and persistence
Section titled “Model and persistence”PivotChartModel version 2 contains:
- stable
chartIdandchartType; - link state and an optional unlinked
datasetsnapshot; - totals, series selection, values-on-rows measure, and semantic bindings;
- presentation, renderer theme, and validated chart options;
- authored axes, per-series overrides, interaction mode, and semantic selection;
- navigation controls and the authored category/time viewport;
- the authored chart-local query, including its slice, filters, sort, and ranking;
- 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. Optional model.limits contains the authored
partial budget overrides and survives JSON save/restore. Missing limits in an existing version 2 model inherit
plugin configuration. Restoring captured data validates it against the effective
budget before renderer creation. Older model versions are rejected rather
than implicitly migrated. Supply chartId in PivotChartRestoreOptions only
when the application intentionally replaces the persisted identity.
Custom renderer contract
Section titled “Custom renderer contract”Renderers and lifecycle
Inspect the renderer's declared capabilities and the chart it creates.
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, axes, series overrides, theme,
locale text, and chart/preview render mode. It also supplies interaction mode,
persistent selection, derived peer highlightSelections, and activation and
clear callbacks. Call onNodeClick for semantic mark activation and
onSelectionClear for a user clear action; the plugin dispatches these according
to the interaction mode. A custom renderer must not mutate the supplied dataset
or model state, or persist peer highlights as local selection.
A renderer can implement optional synchronous validate(input) preflight.
Throw when the complete candidate input requests a feature the backend cannot
preserve. The plugin runs this hook before renderer creation/update and native
selection-filter effects; the hook must be side-effect-free. Existing renderers
can omit it. Direct renderer consumers must also receive the same validation
from the renderer’s own create and update methods.
Configure the renderer before creating a chart. Renderer injection is a runtime
configuration, and is not serialized in the chart model. Replacing that
configuration does not migrate an existing chart instance to another backend.
Each chart retains its captured factory, validator, and capability contract.
Changing pivotCharts.renderer applies to newly created charts. Existing chart
controls, previews, updates, and exports continue using their original backend.
The optional ECharts Canvas adapter
uses this boundary with an explicit supported feature set.
Navigation-capable renderers receive the canonical dataset, authored navigation
and viewport, and onViewportChange. Request a semantic window through that
callback instead of modifying Pivot filters or the supplied dataset. Window-only
updates use the chart’s update queue and do not load another provider dataset.
Custom renderers must advertise capabilities.navigation: true to accept
authored navigation or viewport settings. Omitting that capability preserves
existing renderer integrations and rejects unsupported navigation requests.
The UI intersects the chart catalog with the existing backend’s capabilities.
interactionModes and chartOptionKeys can restrict modes and option controls;
omitting them preserves legacy catalog behavior. An empty interactionModes
list disables authored interaction. A backend’s validate hook remains
responsible for additional option combinations and data-specific restrictions.
Download and image actions are available only when the renderer advertises and
implements them.
Standard UI API
Section titled “Standard UI API”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.
Lifecycle events
Section titled “Lifecycle events”| Event | Detail |
|---|---|
pivot-chart-created | Chart ID and PivotChartRef. |
pivot-chart-updated | Chart ID, update reason, and cloned model. |
pivot-chart-destroyed | Chart ID. |
pivot-chart-node-click | Semantic category/series, paths, measure, and aggregator. |
pivot-chart-error | Optional chart ID and normalized Error. |
pivot-chart-before-download | Cancelable download proposal with owned model/options, format, and operation ID. |
pivot-chart-downloaded | The download action completed; this does not confirm that the browser saved a file. |
pivot-chart-download-error | A download failed or was aborted, with its operation ID and error. |
pivot-chart-before-selection | Cancelable semantic selection proposal. |
pivot-chart-selection-changed | Committed selection with origin, operation ID, and revision. |
pivot-chart-selection-request | Event-mode proposal for explicit application acceptance. |
pivot-chart-selection-error | Failed selection/filter transition or cleanup. |
pivot-chart-before-drill | Cancelable transition with from/to drill state. |
pivot-chart-drill-start | Pending drill transition. |
pivot-chart-drilled | Successful transition with model and dataset. |
pivot-chart-drill-error | Failed transition and error. |
pivot-chart-drill-reset | Successful reset transition. |
pivot-chart-drill-sync | Synchronization request and selected mode. |
Update reasons are data, options, theme, relink, and drill.
Previous: Customization and export · Next: Server data and performance · API reference