Skip to content

Data and Channel Reference

Most charts need only fields and measures. Read this reference when you implement a server provider, choose specialized channels such as X/Y, or build a custom renderer.

Category means a group such as North. Series means a set of comparable values such as Q1 sales. A binding connects one of these values to a chart role such as X, Y, size or target. Stable IDs identify values even when their display labels change.

Interactive example

Datasets and bindings

Compare the chart with its row-major data matrix, including null and formatted values.

The example loads when visible.

interface PivotChartDataset {
revision: number;
source: 'client' | 'server';
categories: PivotChartCategory[];
series: PivotChartSeries[];
values: Array<Array<number | null>>;
displayValues?: Array<Array<string | null>>;
hierarchies?: {
row?: PivotChartHierarchyDefinition;
column?: PivotChartHierarchyDefinition;
};
analyticalFrame?: PivotChartAnalyticalFrame;
}

values is row-major: values[categoryIndex][seriesIndex]. Optional displayValues preserve the Pivot’s formatted values for chart labels, tooltips, data tables, and accessibility text. Categories and series retain stable IDs, member paths, labels, member kinds, measures, and drill hierarchy metadata.

The dataset revision identifies the committed Pivot snapshot that produced the frame. Linked refreshes and drill requests use it to reject stale work.

interface PivotChartAnalyticalFrame {
fields: PivotChartFieldDescriptor[];
observations: PivotChartObservation[];
matrixCells?: Array<{
categoryId: string;
seriesId: string;
observationId: string;
measureFieldId: string;
}>;
hierarchies?: PivotChartDataset['hierarchies'];
derived?: {
bins?: PivotChartJsonValue[];
quantiles?: PivotChartJsonValue[];
distributions?: PivotChartDistribution[];
ranges?: PivotChartJsonValue[];
flowEdges?: PivotChartJsonValue[];
financial?: PivotChartJsonValue[];
geographicFeatures?: PivotChartJsonValue[];
};
}

Fields declare a stable ID, label, dimension/measure role, semantic type, source field, aggregator, and optional format. Each observation stores dimension values separately from numeric measures and optional display measures. Providers and custom renderers can use this metadata independently of visible labels. Built-in statistical charts use the typed distribution views; built-in measure-channel bindings resolve matrix series identities.

Use matrixCells when supplied observations or measure fields have their own IDs. Each entry maps one matrix cell to one measure on a tidy observation. A single observation can therefore carry several measures:

dataset.analyticalFrame = {
fields: [
{ id: 'region-code', label: 'Region', role: 'dimension', semanticType: 'identifier' },
{ id: 'revenue', label: 'Revenue', role: 'measure', semanticType: 'number' },
{ id: 'margin', label: 'Margin', role: 'measure', semanticType: 'number' },
],
observations: [{
id: 'report-row-42',
dimensions: { 'region-code': { value: 'north', label: 'North' } },
measures: { revenue: 120, margin: 18 },
}],
matrixCells: [
{ categoryId: 'north', seriesId: 'sales-series', observationId: 'report-row-42', measureFieldId: 'revenue' },
{ categoryId: 'north', seriesId: 'margin-series', observationId: 'report-row-42', measureFieldId: 'margin' },
],
};
// The corresponding matrix must contain [[120, 18]], in those series positions.

Map every matrix cell once, including null cells, and reference every supplied observation. IDs must exist, referenced fields must be measures, and each observation/measure pair maps to one cell. Matrix values remain authoritative; conflicting numbers or display strings are rejected. Extra dimension metadata and ancillary fields remain metadata; they do not redefine matrix aggregation.

Projection retains mapped observation IDs and metadata for surviving cells. Removing a selected series removes its mapped measure, rather than retaining that excluded value in a stale analytical frame. Unlinking and JSON restoration retain the explicit mapping. Existing generated canonical frames remain supported; arbitrary supplied IDs without a mapping are rejected with an actionable error. Observation IDs are opaque identities, so applications should not construct or split generated IDs.

PivotChartBindings declares renderer channels. For the built-in renderer, measure channels refer to IDs from dataset.series, and the flow dimensions use pivot:category and pivot:series. Empty and omitted channels are equivalent.

Channel groupChannelsUsed by
Value selectionvalueStatistical distributions, histogram, strip/dot, waffle, calendar, and annotated time series.
Relationshipx, y, sizeScatter, bubble, density, and connected-scatter views.
Flowsource, target, weightSankey and chord.
Rangestart, end, low, highTimeline, range, confidence, and error views.
Financialopen, high, low, close, volumeCandlestick, OHLC, and volume-price.
KPIactual, target, varianceBullet, gauge, KPI, and progress gauge.

Other typed channels are extension points for custom renderers. The built-in renderer derives ordinary categories, hierarchy, polar layout, and facets from the matrix; facetRow, facetColumn, label, tooltip, shape, angle, and radius do not configure these native views. Calendar accepts color as a fallback value-series binding. Use colors and the label/tooltip formatter APIs for native appearance. Preserving an extra analytical field does not make it a native rendering channel.

The chart gallery checks required channel counts before selection. For relationship charts, the Layout panel infers distinct X/Y measures when possible and prevents the same field from satisfying both required channels.

await chart.update({
chartType: 'bubble',
bindings: {
x: ['measure:cost:sum'],
y: ['measure:revenue:sum'],
size: ['measure:units:sum'],
},
});

Use matrix series IDs for these native measure bindings, not visible labels or arbitrary analytical-frame field IDs. Some specialized channels can infer an unambiguous semantic alias such as low or close; explicit IDs are preferable when captions are localized or several candidates match.

Box plots and violin charts use original numeric observations for one category and measure. They never treat unrelated aggregated measure columns as samples. Client Pivot queries the committed, filtered original source lazily when a statistical chart is selected; calculated measures cannot supply raw samples. The sample allocation is bounded by maxDataPoints and cached per data revision and chart scope. No observations are silently sampled or truncated.

Server providers and standalone datasets can supply distributions. Preserve any existing matrixCells, fields, and observations when adding derived statistics:

dataset.analyticalFrame = {
...dataset.analyticalFrame,
fields: dataset.analyticalFrame?.fields ?? [],
observations: dataset.analyticalFrame?.observations ?? [],
derived: {
...dataset.analyticalFrame?.derived,
distributions: [{
kind: 'samples',
categoryId: dataset.categories[0].id,
seriesId: dataset.series[0].id,
samples: [1, 2, 3, 4, 100],
}],
},
};

Each category/series pair must be unique and refer to existing matrix members. Samples must be finite numbers. Empty samples omit that mark; singleton and constant samples remain valid. Quartiles use linear interpolation and whiskers use the outermost observations within 1.5 interquartile ranges. Outliers retain the actual observation value for tooltips and click events.

A provider can instead supply a kind: 'summary' entry with count, minimum, lowerQuartile, median, upperQuartile, maximum, lowerWhisker, and upperWhisker, plus optional outliers and mean. Violin charts additionally require density: [{ value, density }], ordered by strictly increasing value, with finite nonnegative density and at least one positive density. Precomputed summaries draw the supplied statistics; the renderer does not invent samples.

Derived distributions survive selection, caching, unlinking, and JSON model save/restore. The older opaque derived.quantiles field remains accepted as metadata but does not enable statistical charts. Range interval charts retain their separate min/max semantics across bound matrix series.

Canonical field descriptors retain their semantic type and format through selection and model persistence. Generated observation IDs are opaque; do not construct or split them. For provider-owned observation IDs and fields, supply the complete matrixCells mapping. The matrix remains authoritative for measures and display strings; mapped metadata survives selection and model persistence.

annotatedTimeSeries, smallMultiples, columnLine, and areaLine accept the typed policy axes: { x: { scale: 'category' | 'time' } }. Category spacing is the default. Select Display → X-axis scale → Time to position points by actual elapsed time. Time input comes from the last semantic category path member, never its localized display label. Accepted values are valid ISO calendar dates (UTC), ISO timestamps with an explicit zone, and numeric epoch milliseconds. Ambiguous civil timestamps, impossible dates, and empty total-member paths fail with INVALID_DATA_SHAPE; exclude totals when using a time axis.

Time coordinates sort chronologically with stable original ordering for equal instants. Tooltips and drill events retain the original category and value. Every small-multiple panel shares the same exact X domain. Singleton/equal instants are centered. Tick formatting uses UTC and available panel width. Missing, null, or nonfinite Y values split paths before point sampling, so sampled lines cannot connect across missing observations.

Axis settings survive JSON model persistence and linked refreshes. An axes update replaces the axes configuration; axes: {} restores defaults. A programmatic time policy on an unsupported chart type is rejected. The gallery clears incompatible policies when switching chart types.

Combination value axes and series overrides

Section titled “Combination value axes and series overrides”

columnLine and areaLine support independent primary (axes.y) and secondary (axes.ySecondary) value axes. Each accepts scale: 'linear' | 'log', finite min/max bounds, title, a tick-only unit, and a serializable tickFormat:

await chart.update({
axes: {
y: { min: 0, max: 100_000, title: 'Revenue', unit: 'USD',
tickFormat: { notation: 'compact', maximumFractionDigits: 1 } },
ySecondary: { scale: 'log', min: 1, max: 1_000, title: 'Orders' },
},
seriesOverrides: {
[revenueSeriesId]: { type: 'column', yAxis: 'primary' },
[ordersSeriesId]: { type: 'line', yAxis: 'secondary' },
},
});

Overrides use stable dataset series IDs and accept type: 'column' | 'line' | 'area' and yAxis: 'primary' | 'secondary'. Unspecified series retain the combination defaults: the first series is column/area, the remaining series are lines, and every series uses the primary axis. Dormant IDs remain in the model and apply when those series return. Multiple columns are grouped side by side; areas draw before columns and lines. Time columns reserve space at the endpoint groups and use bounded widths based on distinct instant gaps.

A log axis requires positive observations and bounds, and supports line series only. Invalid assignments or domains fail with INVALID_DATA_SHAPE before rendering. Explicit domains clip geometry without changing canonical values, tooltips, or exports; fully clipped observations have no focus targets. Linear column/area baselines use zero clamped to the visible domain. A secondary axis reserves space only when an assigned active series has finite observations.

The primary title falls back to presentation.yAxisTitle; the secondary title is independent. Units are never inferred. tickFormat.notation is standard, compact, or scientific; optional minimum/maximum fraction digits are integers from 0 to 20 with minimum no larger than maximum. Authored formatting uses the runtime Intl locale; without it, ticks retain the locale text number formatter. Runtime label customization receives axis identity y or ySecondary.

Axes and overrides are independently replaced on update. Omit a property or use undefined to retain it; use {} to reset it. JSON restore, linked refresh, and drill preserve both. Other chart types reject unsupported authored value axes/assignments; clear these properties when switching programmatically.

Candlestick and OHLC role bindings can contain parallel arrays for multiple groups. Open/high/low helpers can broadcast, while each close field uniquely owns its group and X/Y assignments. See candlestick and OHLC collections. Volume-price adds one distinct paired volume measure per close owner and keeps shared price/volume Y roles.

See server responses, custom renderers and Pivot aggregation rules.