Built-in charting (one prop)

Turn on the built-in Chart panel with a single charting prop - no external library. Pick Group by / Value, choose a type, filter a column or click a bar, and the chart re-aggregates over the grid's current (filtered / sorted) rows live.

A live, editable Svelte 5 data grid example from the SvGrid gallery (Charts). See the SvGrid documentation for the full API.

About this example

The built-in chart panel of the Svelte 5 data grid from a single charting prop, no external library. The Chart toolbar button opens a docked panel, open by default here, where you pick Group by and Value and a chart type; filter or sort the grid and the chart re-draws live, select a cell range and it scopes to those rows, and click a bar or slice to filter the grid to that category. Everything the hand-wired integrated-charts demo does, with no glue code; the engine is in the MIT core.

Everything demo 147 wires by hand - aggregate the displayed rows, render a chart, keep it in sync, cross-filter - is a single charting prop here. Click the "Chart" toolbar button (open by default below), pick a group-by / value, and:

  • filter or sort the grid -> the chart re-draws live
  • select a cell range -> the chart scopes to those rows
  • click a chart bar/slice -> the grid filters to that category The chart engine is MIT core; no extra import, no glue.

Imports, features and API used

Imports: @svgrid/grid

Table features registered: rowSortingFeature, columnFilteringFeature

Columns: rep (Rep), region (Region), product (Product), quarter (Quarter), channel (Channel), revenue (Revenue), margin (Margin), deals (Deals), units (Units)

Frequently asked questions

What does the charting prop accept?

true for defaults, or an object with defaultOpen, position and width for the docked panel plus dimension for the group-by column, series for a split-by column, measures, reduce, defaultType and crossFilter; the panel's pickers change them live.

How does cross-filtering work?

With crossFilter on, clicking a category in the chart filters the grid on the charted dimension, so only that category's rows show; clicking again clears it.

Which columns can be charted?

Numeric columns are offered as measures and text columns as group-by fields, read from the column definitions and their cellDataType; the panel needs at least one of each.

Related documentation

Related articles

Source code (353-built-in-charting.svelte)

<!-- Documented in: docs/help/charts/from-the-grid.md -->
<script lang="ts">
  /**
   * 353. Built-in charting (one prop)
   * ---------------------------------
   * Everything demo 147 wires by hand - aggregate the displayed rows, render a
   * chart, keep it in sync, cross-filter - is a single `charting` prop here.
   * Click the "Chart" toolbar button (open by default below), pick a group-by /
   * value, and:
   *   - filter or sort the grid           -> the chart re-draws live
   *   - select a cell range               -> the chart scopes to those rows
   *   - click a chart bar/slice           -> the grid filters to that category
   * The chart engine is MIT core; no extra import, no glue.
   */
  import {
    SvGrid,
    tableFeatures,
    rowSortingFeature,
    columnFilteringFeature,
    type GridColumns,
  } from '@svgrid/grid'

  const features = tableFeatures({ rowSortingFeature, columnFilteringFeature })

  type Sale = {
    id: number
    rep: string
    region: string
    product: string
    quarter: string
    channel: string
    revenue: number
    deals: number
    units: number
    margin: number
  }
  const REGIONS = ['Americas', 'EMEA', 'APAC']
  const PRODUCTS = ['PLC', 'Drivers', 'Rivets', 'Stock']
  const QUARTERS = ['Q1', 'Q2', 'Q3', 'Q4']
  const CHANNELS = ['Direct', 'Partner', 'Online']
  const NAMES = ['Ada', 'Grace', 'Alan', 'Margaret', 'Linus', 'Donald', 'Brian', 'Dennis']
  let seed = 0x51ce
  const rnd = () => ((seed = (seed * 1103515245 + 12345) >>> 0) / 0xffffffff)
  const rows: Sale[] = Array.from({ length: 96 }, (_, id) => {
    const revenue = Math.round(10_000 + rnd() * 90_000)
    return {
      id,
      rep: NAMES[id % NAMES.length]!,
      region: REGIONS[id % 3]!,
      product: PRODUCTS[id % 4]!,
      quarter: QUARTERS[id % 4]!,
      channel: CHANNELS[id % 3]!,
      revenue,
      deals: Math.round(2 + rnd() * 30),
      units: Math.round(20 + rnd() * 480),
      margin: Math.round(revenue * (0.12 + rnd() * 0.28)),
    }
  })

  const money = { type: 'currency', currency: 'USD', options: { maximumFractionDigits: 0 } } as const
  const columns: GridColumns<Sale> = [
    { field: 'rep', header: 'Rep', width: 110 },
    { field: 'region', header: 'Region', width: 120 },
    { field: 'product', header: 'Product', width: 120 },
    { field: 'quarter', header: 'Quarter', width: 100 },
    { field: 'channel', header: 'Channel', width: 110 },
    { field: 'revenue', header: 'Revenue', width: 140, align: 'right', cellDataType: 'number', format: money },
    { field: 'margin', header: 'Margin', width: 130, align: 'right', cellDataType: 'number', format: money },
    { field: 'deals', header: 'Deals', width: 90, align: 'right', cellDataType: 'number' },
    { field: 'units', header: 'Units', width: 100, align: 'right', cellDataType: 'number' },
  ]
</script>

<div class="demo-page" style="height: 620px; display: flex; flex-direction: column;">
  <p class="demo-hint" style="margin: 0 0 8px;">
    The whole grid below is one <code>&lt;SvGrid ... charting /&gt;</code>. Try the
    <strong>Group by</strong> / <strong>Value</strong> pickers, filter a column, or click a bar.
  </p>
  <div style="flex: 1; min-height: 0;">
    <SvGrid
      columnResize
      data={rows}
      {columns}
      {features}
      sortable
      filterable
      filterMode="row"
      selectionMode="both"
      containerHeight="100%"
      charting={{ defaultOpen: true, width: 460 }}
    />
  </div>
</div>

View this example on GitHub

More Charts examples

  • Chart a selection (context menu) - With integrated charting enabled, the right-click menu gains a Chart selected range item: select a block of cells, right-click, and the chart panel opens scoped to that range - the Excel chart-this gesture, built in. The item appears only when charting is on and is appended to the default context menu automatically.
  • Chart view of the grid - The `chart` prop turns the same <SvGrid> into a chart, driven by the grid’s filtered + sorted rows (search + sort flow through). A view of the grid like board and scheduler, but the renderer is free: the grid lazy-loads a built-in view wrapping the standalone SvChart via rowsToChartSpec. Flip Table <-> Chart (bar / line / area) over one source of truth.
  • Candlestick / OHLC - Candlestick and OHLC price marks with an ordinal date axis. ChartSeries.ohlc carries the four prices while values keeps the closes, so the CSV export, the screen-reader table and a 10-day moving average all work with no candle-specific code. Toggle the axis: a real time axis opens a gap over every weekend, an ordinal one spaces sessions evenly and still labels them by date. The strip under the plot is the chart brush: drag its window to pan, drag an edge to resize.
  • Box plot + error bars - Distribution rather than average: box plots with the 1.5 IQR whisker rule and individual outliers, next to the same data as a bar chart of the means with error bars. two regions with nearly identical means sit side by side in the bars and look nothing alike in the boxes. boxStats() summarises a raw sample, rowsToBoxSpec() does it per group, and ChartSeries.errors annotates any existing mark without changing its type.
  • Axes, titles and styling - The chart hands the decisions back: a numeric x axis that spreads payload sizes the way the numbers do, pinned domains with a fixed tick interval and a formatter per axis, grid lines on or off, a shaded budget band, a vertical reference line, per-point markers and colours, a stepped dashed series on the right axis, a title / subtitle / caption, a legend on any side, and a tooltip snippet in single-series mode. Below it, 50,000 monitoring readings decimated to one point per pixel with LTTB or min / max - toggle it off to see the cost.