Skip to content

Histogram Brush Filter

The histogram brush is useful for prices, durations, revenue, latency, and other numeric fields where users benefit from seeing the distribution before choosing a range. It reads finite parsed values from the column and commits an inclusive numeric interval.

Source code
TypeScriptts
grid.plugins = [AdvanceFilterPlugin];
grid.columns = [
  {
    prop: 'revenue',
    name: 'Revenue',
    filter: ['number', FILTER_HISTOGRAM_BRUSH],
  },
];
grid.filter = true;

return [
  { revenue: 0 },
  { revenue: 50 },
  { revenue: 75 },
  { revenue: 110 },
  { revenue: 200 },
  { revenue: 275 },
  { revenue: 410 },
  { revenue: 600 },
  { revenue: 850 },
  { revenue: 1000 },
];

AdvanceFilterPlugin registers the built-in type automatically. Add its stable ID to a numeric column:

import { defineCustomElements } from '@revolist/revogrid/loader';
import {
AdvanceFilterPlugin,
FILTER_HISTOGRAM_BRUSH,
} from '@revolist/revogrid-pro';
import '@revolist/revogrid-pro/dist/revogrid-pro.css';
defineCustomElements();
const grid = document.createElement('revo-grid');
grid.plugins = [AdvanceFilterPlugin];
grid.columns = [
{ prop: 'product', name: 'Product' },
{
prop: 'revenue',
name: 'Revenue',
filter: ['number', FILTER_HISTOGRAM_BRUSH],
},
];
grid.filter = true;
document.querySelector('#app')!.append(grid);
grid.source = [
{ product: 'Alpha', revenue: 120 },
{ product: 'Beta', revenue: 480 },
{ product: 'Gamma', revenue: 950 },
];
  • Type ID: FILTER_HISTOGRAM_BRUSH ('histogramBrush')
  • Operator ID: HISTOGRAM_BRUSH_BETWEEN ('histogramBrushBetween')
  • Value: { min: number, max: number, inclusive: true }

Only finite parsed values participate in the histogram and range match. Returning both handles to the complete numeric domain removes the no-op condition. A logarithmic scale falls back to linear when the data includes zero or negative values.

Use the same operator and JSON-safe value in multiFilterItems:

import {
HISTOGRAM_BRUSH_BETWEEN,
defineAdvancedFilterConfig,
} from '@revolist/revogrid-pro';
grid.filter = defineAdvancedFilterConfig({
multiFilterItems: {
revenue: [
{
id: 1,
type: HISTOGRAM_BRUSH_BETWEEN,
value: { min: 250, max: 800, inclusive: true },
relation: 'and',
},
],
},
});

Replace the default registration with a configured instance. Passing only the replacement is enough; the plugin keeps the other built-ins.

import {
createHistogramBrushStructuredFilterType,
defineAdvancedFilterConfig,
} from '@revolist/revogrid-pro';
const histogram = createHistogramBrushStructuredFilterType({
bins: 12, // a positive number or 'auto'
scale: 'log',
formatValue: (value) => `$${value.toLocaleString()}`,
formatMatchCount: (count) => `${count.toLocaleString()} rows`,
chart: {
type: 'line', // 'bar' | 'line' | 'area'; default is 'bar'
showPoints: true,
formatTooltip: (bin, { minLabel, maxLabel, selected }) => ({
title: `${minLabel} – ${maxLabel}`,
details: [`${bin.count} rows`, selected ? 'Selected' : 'Outside selection'],
}),
},
});
grid.filter = defineAdvancedFilterConfig({
structuredFilterTypes: [histogram],
});

bins: 'auto' uses a deterministic Sturges-rule count, capped for predictable rendering. A fixed count is normalized to the supported range. Use cellParser on the column when stored values need conversion before numeric filtering.

The chart and range slider are separate shared controls. Default per-bin tooltips are keyboard reachable and localize through histogramBrushChart, histogramBrushItem, histogramBrushItems, histogramBrushSelected, and histogramBrushOutsideSelection captions. formatTooltip can return different title/detail content for every bin.

  • Omitting AdvanceFilterPlugin; the Core filter plugin does not render structured bodies.
  • Adding the operator ID to column.filter; columns opt in with FILTER_HISTOGRAM_BRUSH, not HISTOGRAM_BRUSH_BETWEEN.
  • Restoring strings such as '250'; the saved bounds must be finite numbers and inclusive must be true.
  • Expecting scale: 'log' with zero or negative data; the editor intentionally uses linear geometry instead.
  • Reassigning grid.filter with only multiFilterItems after configuring a custom registration; include structuredFilterTypes again or update the plugin state through its public API.