pax.BlazorChartJs is a Blazor wrapper for Chart.js. It renders charts from typed .NET configuration models through a reusable ChartComponent and a JavaScript isolation module.
| Release | Chart.js | Tested Chart.js |
|---|---|---|
| >= 0.5.0 | 4.x | 4.5.1 |
- Typed chart configuration models for common Chart.js charts, datasets, scales, plugins, callbacks, and scriptable/indexable options.
- A Blazor
ChartComponentthat owns chart lifecycle, event forwarding, image capture, resizing, visibility, and legend helpers. - Targeted chart updates for labels, data, datasets, and options, including one batched smooth dataset synchronization path.
- Registered JavaScript callbacks referenced from C# through
ChartJsFunctioninstead of raw JavaScript in serialized chart configs. - App-wide Chart.js defaults through
AddChartJs(...)and per-chart options when a project needs shared styling or callbacks. - Browser-tested sample pages that show runnable charts together with the C# and JavaScript needed for the Chart.js sample behavior.
ChartJsFunctionand callback module support for tooltip, legend, tick, datalabel, dataset, padding, and other scriptable option paths.- Expanded typed coverage for Chart.js core options, element options, dataset defaults, tooltip callbacks, decimation, and remaining v4.5.1 option gaps.
ChartJsSetupOptions.Defaults,ChartJsDefaultsOptions, andChartJsOptionsDatasetsfor app-wideChart.defaultsconfiguration.ChartJsConfig.SetDatasetsSmooth(...)to add, update, remove, reorder, and optionally relabel datasets in one smooth update.ChartJsConfig.SetDatasetBinaryData(...)andChartJsBinaryPayloadhelpers for large Y and XY dataset updates without JSON-serializing the data arrays.- A Chart.js sample gallery with official sample sections, sample actions, visible C#/JavaScript code, and Playwright coverage.
Start with the live TestPage or the reusable sample library.
The Chart.js sample gallery mirrors the official sample set as runnable Blazor components. It covers bar, line, area, other chart types, scales, scale options, legends, titles, subtitles, tooltips, scriptable options, animations, advanced samples, and plugin samples. Library-specific demos cover events, HTML legends, datalabels, callback modules, plugin registration, update flows, and multiple-chart scenarios.
dotnet add package pax.BlazorChartJsProgram.cs:
builder.Services.AddChartJs(options =>
{
// default
options.ChartJsLocation = "https://cdn.jsdelivr.net/npm/chart.js";
options.ChartJsPluginDatalabelsLocation = "https://cdn.jsdelivr.net/npm/chartjs-plugin-datalabels@2";
});If you want to serve Chart.js locally, you can provide your own URLs:
builder.Services.AddChartJs(options =>
{
var version = "4.5.1";
options.ChartJsLocation = $"/_content/dsstats.weblib/js/chart.umd.min.js?v={version}";
options.ChartJsPluginDatalabelsLocation = "/_content/dsstats.weblib/js/chartjs-plugin-datalabels.min.js";
});The wrapper uses Blazor JavaScript isolation, so consumers do not need to add a global interop script to the page and the module does not pollute the global JavaScript namespace.
@using pax.BlazorChartJs
<div class="chart-container w-75">
<ChartComponent ChartJsConfig="chartJsConfig" />
</div>
@code {
private readonly ChartJsConfig chartJsConfig = new()
{
Type = ChartType.bar,
Data = new ChartJsData()
{
Labels = ["Jan", "Feb", "Mar"],
Datasets =
[
new BarDataset()
{
Label = "Dataset 1",
Data = [1, 2, 3]
}
]
}
};
}See the sample minimal chart for a complete component and the rest of the sample library for chart-type examples.
Prefer targeted updates when an existing chart can be changed safely:
ChartJsConfig.SetLabels(...)ChartJsConfig.AddData(...)andChartJsConfig.SetData(...)ChartJsConfig.AddDatasetSmooth(...)andChartJsConfig.SetDatasetsSmooth(...)ChartJsConfig.UpdateChartOptions()for options-only changesChartJsConfig.ReinitializeChart()when a full chart reinitialization is actually needed
SetDatasetsSmooth(...) adds, updates, removes, and reorders datasets by id in one smooth chart update. Optional labels and current options can be applied in the same pass:
chartJsConfig.Options ??= new ChartJsOptions();
chartJsConfig.Options.Responsive = false;
chartJsConfig.SetDatasetsSmooth(
datasets:
[
new BarDataset
{
Id = "dataset-2",
Label = "Dataset 2",
Data = [ 4, 5, 6 ]
},
new BarDataset
{
Id = "dataset-1",
Label = "Dataset 1",
Data = [ 3, 2, 1 ]
}
],
labels: ["Apr", "May", "Jun"],
updateOptions: true);Use ChartJsConfig.SetDatasetBinaryData(...) to update a dataset by id from a packed binary payload without serializing large data arrays as JSON. ChartJsBinaryPayload creates compact payloads for common Y and XY layouts:
chartJsConfig.SetDatasetBinaryData(
ChartJsBinaryPayload.FromY("dataset-1", new float[] { 10, 12, 14 }));
var points = new ChartJsPoint[]
{
new(1, 20),
new(2, 21),
new(3, 22)
};
chartJsConfig.SetDatasetBinaryData(
ChartJsBinaryPayload.FromXY("dataset-2", points));FromY(...) accepts int, float, or double spans. FromXY(...) accepts ChartJsPoint spans or interleaved double values. Custom strided binary layouts can still be passed with ChartJsBinaryDatasetPayload directly.
ChartJsFunction.FromName(...) can be used to reference JavaScript callbacks from C# chart configuration without serializing raw JavaScript into the config. Configure a callback module that exports a chartJsCallbacks object:
builder.Services.AddChartJs(options =>
{
options.ChartJsCallbacksModuleLocation = $"{builder.HostEnvironment.BaseAddress}_content/pax.BlazorChartJs.samplelib/chartJsCallbacks.js";
});Then reference registered callback names from chart options or datasets:
new BarDataset()
{
Label = "Dataset 1",
Data = new List<object>() { 1, 2, 3 },
BackgroundColor = ChartJsFunction.FromName("createRepeatFillPattern")
}
new Legend()
{
Labels = new Labels()
{
Filter = ChartJsFunction.FromName("showLegendItem")
}
}
new LinearAxisTick()
{
Callback = ChartJsFunction.FromName("formatCurrency")
}Callback names are validated and resolved from the configured module, which avoids raw JavaScript serialization in the chart config. See the full ChartJsFunction callback sample.
Beyond script locations and callback modules, AddChartJs(...) can configure app-wide Chart.js defaults.
builder.Services.AddChartJs(options =>
{
options.ChartJsCallbacksModuleLocation = $"{builder.HostEnvironment.BaseAddress}_content/my-app/chartJsCallbacks.js";
options.Defaults = new ChartJsDefaultsOptions()
{
Color = "#1f2937",
BorderColor = "#d1d5db",
Font = new Font
{
Family = "Inter, system-ui, sans-serif",
Size = 12
},
Datasets = new ChartJsOptionsDatasets()
{
Bar = new
{
barPercentage = 0.8,
categoryPercentage = 0.9
},
Line = new
{
tension = 0.25
}
},
OnClick = ChartJsFunction.FromName("globalChartClick")
};
});Defaults maps to Chart.defaults and is applied after Chart.js is loaded and before the first chart is constructed. Per-chart ChartJsConfig.Options still override the global defaults. ChartJsFunction values in defaults use the same callback registry configured by ChartJsCallbacksModuleLocation.
Several chart events are available. By default only the init event is emitted; enable the others in ChartJsConfig.Options. See the events sample.
- click
- hover
- leave
- progress
- complete
- resize
- chartjs-plugin-datalabels
- ArbitraryLines (YouTube)
- Custom plugins through the custom plugin sample
Several chart functions are available in the ChartComponent, e.g.:
ChartComponent.ResizeChart(...)ChartComponent.GetChartImage(...)ChartComponent.ToggleDataVisibility(...)
We really like people helping us with the project. Nevertheless, take your time to read our contributing guidelines here.
The TypeScript source for the packaged JavaScript isolation module lives in src/pax.BlazorChartJs/TypeScript.
When those sources are newer than the tracked bundle, dotnet build restores the local Node packages and regenerates
wwwroot/chartJsInterop.js before the library static web assets are resolved. Node and npm are required for that
regeneration path.
To regenerate the bundled browser asset directly:
cd src\pax.BlazorChartJs
npm install
npm run bundleThe bundle command writes the single shipped module to wwwroot/chartJsInterop.js.
v0.9.0
- Breaking change: font option properties that now support scriptable values use
IndexableOption<Font>in those contexts. Target-typedFont = new()no longer binds there; useFont = new Font { ... }or aChartJsFunctioncallback.- Added
ChartJsFunctionto reference registered JavaScript callbacks from C# chart configuration without serializing raw JavaScript.- Added callback module configuration and marker revival for chart initialization, option updates, and dataset add/update/set interop calls.
- Added scriptable callback support for datalabel formatters, axis ticks, tooltip callbacks, legend callbacks, and indexable color options.
- Expanded
IndexableOption<T>to support single values, indexed values, andChartJsFunctioncallback values.- Expanded
Paddingto support Chart.js numeric padding,{x, y}shorthand padding, and scriptable padding callbacks while preserving existingPadding?property types.- Added a scriptable padding sample with a sample-only
Latestlabel plugin.- Hardened callback resolution with flat JavaScript identifier validation and reserved-name checks.
- Updated sample callback charts to use a shared
chartJsCallbacks.jscallback registry.- Completed the Chart.js v4.5.1 option coverage pass with expanded core, element, dataset, tooltip, label, scale, and decimation option support.
- Added missing global/core Chart.js options to
ChartJsOptions:BackgroundColor,BorderColor,Clip,Color,Datasets,Font,Hover,HoverBackgroundColor,HoverBorderColor,Normalized,OnClick,OnHover, andOnResize.- Added
ChartJsSetupOptions.Defaults/ChartJsDefaultsOptionsto configure app-wideChart.defaultsvalues throughAddChartJs(...).- Added
ChartJsOptionsDatasetsforoptions.datasetsandChart.defaults.datasetschart-type defaults.- Chart.js native
OnClick,OnHover, andOnResizecallbacks are preserved when the Blazor/C# event bridge flags are enabled.- Added
ChartJsConfig.SetDatasetsSmooth(...)to add, update, remove, and reorder datasets by id in one smooth batched chart update, with optional labels and current options update.- Added binary dataset updates through
ChartJsConfig.SetDatasetBinaryData(...)and compactChartJsBinaryPayloadhelper factories for large Y and XY data updates.- Added the official Chart.js sample gallery as runnable Blazor sample pages with visible C#/JavaScript code, sample actions, and Playwright coverage.
v0.8.8
- Dataset interop calls are ignored safely when the target chart was already disposed.
- Reduced allocation and lookup work while resolving and disposing Chart.js instances.
- Refactored library and sample code for .NET 11 analyzer/style guidance.
v0.8.7
- Hardened chart initialization to better handle rapid reinitialization and existing Chart.js instances for the same canvas.
- Resize events now include browser viewport dimensions via
WindowWidthandWindowHeight.ChartJsResizeEvent.WidthandHeightremain chart/container dimensions; useWindowWidthandWindowHeightfor viewport breakpoint logic.ChartJsInitEventnow includes initial chart and viewport dimensions viaWidth,Height,WindowWidth, andWindowHeight.- Dataset updates now match by dataset id across all chart datasets, including hidden datasets.
- Update Microsoft.TypeScript.MSBuild to v6.0.3
v0.8.6
- Updated to .NET 10
- Full JavaScript generation from TypeScript
- Chart.js v4.5.1 test coverage
- Improved JSON serialization to be more AOT‑friendly
v0.8.5
- Microsoft.AspNetCore.Components.Web v8.0.*
- ChartJs v4.4.5 tests
- Test/Sample projects update to dotnet v8.0.10
v0.8.4
- Microsoft.AspNetCore.Components.Web v8.0.8
- ChartJs v4.4.4 tests
v0.8.3
- Microsoft.AspNetCore.Components.Web v8.0.2
- Added ChartJsConfig.UpdateDatasetsSmooth updates the ChartJs dataset(s), instead of replacing.
- Added BlazorLegendBase that can be used for a ChartJs Html Legend - [Sample][https://ipax77.github.io/pax.BlazorChartJs/htmllegendchart]
- Added ChartComponent.GetLegendItems()
- Added ChartComponent.IsDatasetVisible(int datasetIndex)
- Added ChartComponent.SetDatasetPointsActive(int datasetIndex)
- BarDataset.BarPercentage changed from int? to double?
- Renamed Layout to ChartJsLayout (CA1724)
IndexableOptionnow supports Collection Expressions e.g.
BorderColor = ["rgba(255, 99, 132, 1)", "rgba(54, 162, 235, 1)"],
BorderWidth = [1, 2]
- ChartJs v4.4.2 Tests
- Blazor App sample
v0.8.2
- ChartJs v4.4.1 tests
- Catching (more) dispose exeptions when switching from SSR to CSR (rendermode auto - AggregateException, JSDisconnectedException)
v0.8.1
- dotnet 8 Breaking Change
- Added missing pie/doughnut dataset options (Cutout, Radius, Animation)
- The
IndexableOptionnow supports implicit operators, allowing a more concise syntax for initialization.
New Syntax:
BorderColor = new List<string>()
{
"rgba(255, 99, 132, 1)",
"rgba(54, 162, 235, 1)"
},
BorderWidth = 1Old Syntax (still possible):
BorderColor = new IndexableOption<string>(new List<string>()
{
"rgba(255, 99, 132, 1)",
"rgba(54, 162, 235, 1)"
}),
BorderWidth = new IndexableOption<double>(1)v0.6.3
- Reverted Microsoft.TypeScript.MSBuild to v5.2.2 Microsoft.TypeScript.MSBuild v5.3.2 not working for Blazor projects (only working for wasm)
v0.6.2
- Microsoft.AspNetCore.Components.Web upgrade to v6.0.25
- Added missing pie/doughnut dataset options (Cutout, Radius, Animation)
- The
IndexableOptionnow supports implicit operators, allowing a more concise syntax for initialization.
New Syntax:
BorderColor = new List<string>()
{
"rgba(255, 99, 132, 1)",
"rgba(54, 162, 235, 1)"
},
BorderWidth = 1Old Syntax (still possible):
BorderColor = new IndexableOption<string>(new List<string>()
{
"rgba(255, 99, 132, 1)",
"rgba(54, 162, 235, 1)"
}),
BorderWidth = new IndexableOption<double>(1)v0.6.1
- ChartJsLabelClickEvent and ChartJsLabelHoverEvent with 'nearest' DatasetLabel and DatasetIndex
- Microsoft.AspNetCore.Components.Web upgrade to v6.0.21
v0.6.0
- Fix typo for AngleLines in LinearRadialAxis Breaking Change
v0.5.2
- Datalabels per dataset contributed by pjvinson
- ChartJs v4.4.0 tests
v0.5.1
- Marked ChartJsGrid border options as obsolete for v4.x - use ChartJsAxisBorder instead.
- TimeSeriesAxis Min, Max, SuggestedMin and SuggestedMax are of type
StringOrDoubleValue, now.- Microsoft.AspNetCore.Components.Web upgrade to v6.0.16
- ChartJs v4.3.0 tests
- ChartJs v4.3.1 tests
- ChartJs v4.3.3 tests
v0.5.0
- Breaking Changes
- Update to ChartJs v4.x
- Removed ChartJs javascript files - defaults to cdn links, now. Use
options.ChartJsLocation = "mychart.js"to use a custom/local ChartJs version.- Removed chartjs-plugin-labels (you can still register it as custom plugin)
- Microsoft.AspNetCore.Components.Web upgrade to v6.0.13
- Added ScaleAxis X1 and Y1 (override ChartJsOptionsScales for other names)
ChartJsConfig.UpdateChartOptions()(will replaceChartComponent.UpdateChartOptions)ChartJsConfig.ReinitializeChart()(will replaceChartComponent.DrawChart)