Blazor ApexCharts

Installing and configuring ApexCharts in Blazor

Blazor-ApexCharts is a Blazor wrapper for ApexCharts.js that brings interactive, declarative charts to Blazor Server, Blazor WebAssembly, and .NET MAUI applications. The wrapper exposes ApexCharts options through strongly-typed C# classes and a component-based API, so you can build dashboards without writing JavaScript.

This page is the setup and API walkthrough. For an overview of the component, what it supports and how it is licensed, see the Blazor chart component page.

Install

Install the NuGet package in your Blazor project for web (Server / WebAssembly), WinForms, or WPF:

dotnet add package Blazor-ApexCharts

For .NET MAUI projects, install the MAUI package instead:

dotnet add package Blazor-ApexCharts-MAUI

Register the chart service

ApexChartService is an optional scoped service that manages global options, locales, and chart instances. Register it in your Program.cs (or Startup.cs) DI container.

services.AddApexCharts();

You can also pass global options at registration time:

services.AddApexCharts(e =>
{
    e.GlobalOptions = new ApexChartBaseOptions
    {
        Debug = true,
        Theme = new Theme { Palette = PaletteType.Palette6 }
    };
});

Global options are kept per user. Each IApexChartService (one per DI scope, which on Blazor Server is one user circuit) starts from its own copy of the options passed to AddApexCharts, so a change made at runtime through ChartService.GlobalOptions, SetGlobalOptionsAsync or SetLocaleAsync affects only the current user. To change them after startup, call ChartService.SetGlobalOptionsAsync(options, true) in that user's scope. Changing the object you passed to AddApexCharts reaches only chart services created afterwards; before 8.0 that object was shared by every user.

For .NET MAUI use the dedicated extension method:

services.AddApexChartsMaui();

Apply a licence key

Every chart type and every standard option works with no key. Only the premium interaction modules (undo and redo history, perspectives, linked views with crossfilter, ink annotations, measure, the context menu and storyboard) show an APEXCHARTS watermark until a key on the Premium or Enterprise plan is applied; a valid Pro key keeps the watermark. Keys are validated offline, with no network call.

Set the key once in the chart service, so it is applied before any chart renders:

services.AddApexCharts(e =>
{
    e.LicenseKey = builder.Configuration["APEXCHARTS_LICENSE_KEY"];
});

AddApexChartsMaui takes the same option. Without the service, set it per chart with Chart.License:

<ApexChart TItem="MyData"
           Options="@(new ApexChartOptions<MyData> { Chart = new Chart { License = "APEX-your-license-key" } })">
    ...
</ApexChart>

To apply or change a key at runtime, call await ChartService.SetLicenseAsync("APEX-your-license-key");. A chart update after a late Premium or Enterprise key clears the watermark without a full re-render.

Imports

Add a reference to ApexCharts in your _Imports.razor so the components are available in every page:

@using ApexCharts

If you target .NET 8 or later, set the render mode of the page (or component) hosting the chart to one of the interactive modes (InteractiveServer, InteractiveWebAssembly, or InteractiveAuto), otherwise the JavaScript interop will not run.

Your first chart

Drop an <ApexChart> component into a Razor page and add one or more <ApexPointSeries> children to bind your data. The XValue / YValue lambdas tell the chart how to read each item.

<ApexChart TItem="MyData"
           Title="Sample Data">

    <ApexPointSeries TItem="MyData"
                     Items="Data"
                     Name="Net Profit"
                     SeriesType="SeriesType.Bar"
                     XValue="e => e.Category"
                     YValue="e => e.NetProfit" />

    <ApexPointSeries TItem="MyData"
                     Items="Data"
                     Name="Revenue"
                     SeriesType="SeriesType.Bar"
                     XValue="e => e.Category"
                     YValue="e => e.Revenue" />
</ApexChart>

@code {
    private List<MyData> Data { get; set; } = new();

    protected override void OnInitialized()
    {
        Data.Add(new MyData { Category = "Jan", NetProfit = 12, Revenue = 33 });
        Data.Add(new MyData { Category = "Feb", NetProfit = 43, Revenue = 42 });
        Data.Add(new MyData { Category = "Mar", NetProfit = 112, Revenue = 23 });
    }

    public class MyData
    {
        public string Category { get; set; }
        public int NetProfit { get; set; }
        public int Revenue { get; set; }
    }
}

Switching chart types

To turn the bar chart above into a line or area chart, change the SeriesType enum on each ApexPointSeries:

<ApexPointSeries TItem="MyData"
                 Items="Data"
                 Name="Revenue"
                 SeriesType="SeriesType.Line"
                 XValue="e => e.Category"
                 YValue="e => e.Revenue" />

The same applies for SeriesType.Area, SeriesType.Scatter, SeriesType.Bubble, and other point-based series. To read more about the configuration available for each type, see the plotOptions reference.

Donut and Pie charts

Pie, donut, polar area, and radial bar charts use a single dimensional data set. They use the same <ApexPointSeries> component, with the variant selected through SeriesType. Because each category collapses many rows into one value, they normally pair with YAggregate rather than YValue:

<ApexChart TItem="MyData"
           Title="Sales by Category">

    <ApexPointSeries TItem="MyData"
                     Items="Data"
                     Name="Sales"
                     SeriesType="SeriesType.Donut"
                     XValue="e => e.Category"
                     YAggregate="@(e => e.Sum(e => e.NetProfit))"
                     OrderByDescending="e => e.Y" />
</ApexChart>

Switch between the variants with SeriesType.Pie, SeriesType.Donut, SeriesType.PolarArea or SeriesType.RadialBar.

Configuring chart options

ApexChartOptions<T> mirrors the JavaScript options object documented in the ApexCharts options reference. Pass an instance via the Options parameter on <ApexChart>:

<ApexChart TItem="MyData"
           Title="Sales"
           Options="options">

    <ApexPointSeries TItem="MyData"
                     Items="Data"
                     Name="Sales"
                     SeriesType="SeriesType.Line"
                     XValue="e => e.Category"
                     YValue="e => e.NetProfit" />
</ApexChart>

@code {
    private ApexChartOptions<MyData> options = new()
    {
        Theme = new Theme { Mode = Mode.Dark },
        Stroke = new Stroke { Curve = Curve.Smooth, Width = 3 },
    };
}

Each chart instance must have its own ApexChartOptions instance. Options cannot be shared between multiple charts.

Updating chart data

Hold a reference to the <ApexChart> component with @ref and call UpdateSeriesAsync() after mutating the underlying collection:

<button @onclick="ReloadData">Reload</button>

<ApexChart TItem="WeatherForecast"
           Title="Temperature"
           @ref="chart">

    <ApexPointSeries TItem="WeatherForecast"
                     Items="forecasts"
                     Name="Temp C"
                     SeriesType="SeriesType.Line"
                     XValue="e => e.Date"
                     YValue="e => e.TemperatureC" />
</ApexChart>

@code {
    private List<WeatherForecast> forecasts = new();
    private ApexChart<WeatherForecast> chart;

    private async Task ReloadData()
    {
        forecasts = await LoadForecastsAsync();
        await chart.UpdateSeriesAsync(animate: true);
    }
}

UpdateOptionsAsync is the equivalent for changing chart options at runtime. Both methods accept a flag to control whether the change is animated.

Ignite UI theming

From 8.0.0 a chart can take its series palette, text, gridlines, tooltip, font and light or dark variant from the Ignite UI theme on the page. The add-on ships inside the package and needs no extra licence key. Turn it on in the chart service (or AddApexChartsMaui):

services.AddApexCharts(e =>
{
    e.IgniteUI = true;
});

The service loads _content/Blazor-ApexCharts/js/features/ignite-ui.js once, before the first chart renders. Use this option rather than a script tag: the add-on registers on the ApexCharts instance the component loads, which a tag in index.html would not reach. If you register your own IApexChartService implementation, implement InitializeIgniteUIAsync to load the add-on; the interface default does nothing.

Ignite UI is the lowest layer above the built-in defaults. An option you set in ApexChartOptions wins, then the chart's own CSS variables, then the family --apx-* tokens, then a named theme (Theme.Name) or palette (Theme.Palette), then Ignite UI. Per chart:

// Ignite UI colours and font off; --apx-* tokens still apply
Theme = new Theme { DesignSystem = false }

// No token reads at all, --apx-* or --ig-*
Theme = new Theme { Tokens = false }

The chart reads its theme on every render. After a change that does not render, such as swapping the Ignite UI stylesheet for its dark variant, call RefreshTokensAsync() on the chart. The theme names its font but does not load it, so include the font's stylesheet on the page. See Ignite UI theming for what follows the theme.

Content Security Policy

If your page sends a CSP whose style-src lists a nonce instead of 'unsafe-inline', set Chart.Nonce to that nonce. ApexCharts copies it onto the <style> elements it injects; without it the browser blocks them and the chart renders unstyled.

private ApexChartOptions<MyData> options = new()
{
    Chart = new Chart { Nonce = cspNonce }
};

The shared stylesheet is created by the first chart that renders, so that chart must carry the nonce. A nonce generated per request belongs on each chart, or in options passed to the scoped ChartService.SetGlobalOptionsAsync before the first chart renders. Use GlobalOptions in AddApexCharts only for a value that never changes, since it is set once at startup.

Serving the scripts yourself

JavascriptPath points the component at your own copy of blazor-apexcharts.js, for example on a CDN. Set it per chart or in the global options:

services.AddApexCharts(e =>
{
    e.GlobalOptions = new ApexChartBaseOptions
    {
        Blazor = new ApexChartsBlazorOptions
        {
            JavascriptPath = "https://cdn.example.com/charts/blazor-apexcharts.js"
        }
    };
});

From 8.0 the file set is larger. Copy these from _content/Blazor-ApexCharts/js/, keeping their layout:

  • blazor-apexcharts.js, at the path you set
  • apexcharts.esm.js next to it, which is now a small module that loads the next file
  • apexcharts.full.min.js next to it
  • features/ignite-ui.js below it, when IgniteUI is on

Upgrading to 8.0

Blazor-ApexCharts 8.0.0 bundles ApexCharts.js 8.8.1 (7.1.0 bundled 6.5.0). Most code compiles unchanged, with two exceptions, and some defaults change what a click or a scroll does.

Type changes. Assigning these still compiles. Reading them back as double? does not, and assemblies compiled against the old properties need a rebuild.

  • AnnotationsPoint.Y: double? to object, so a point annotation can name a category row (Y = "Beta") on a horizontal bar or rangeBar chart. Numbers are still sent as numbers.
  • AnnotationsYAxis.Width: double? to object. A number is sent as pixels, and a string such as "50%" is sent as it is.

Behaviour changes.

  • A legend click on a pie, donut or polar area chart hides or shows that slice instead of selecting it. OnLegendClicked still runs, but OnDataPointSelection no longer fires from the legend. To select from the legend, call ToggleDataPointSelectionAsync in OnLegendClicked.
  • The mouse wheel zooms only with Ctrl or Cmd held, or a trackpad pinch; a plain wheel scrolls the page and shows a hint. Zoom.AllowMouseWheelZoom = true brings back the old wheel.
  • A series hidden from the legend stays hidden when the chart updates.
  • Data labels that collide across series are moved apart, and bar data labels slide to their new place on an update. DataLabels.Animate.Enabled = false snaps them.
  • --apx-font-family on the page sets the chart font unless Chart.FontFamily is set. A Chart.ForeColor, grid colour or axis colour you set wins over the --apx-fore and --apx-grid tokens, even when it equals the default.
  • Global options are copied per DI scope (see Register the chart service), so code that changed the startup options object to update every user now calls SetGlobalOptionsAsync in each user's scope.
  • With a custom JavascriptPath, copy the larger file set listed under Serving the scripts yourself.

More chart examples

Browse the Blazor-ApexCharts demo site for a gallery of chart types, including line, area, candlestick, heatmap, treemap, radar, range bar, funnel and more, each with a copy-pastable Razor source, alongside pages that document every feature of the component. The component supports the full ApexCharts option surface, so anything documented in the Options reference is available from C#.

Need advanced chart features?

We have partnered with Infragistics to grant you access to an extensive library of data visualizations that enables stunning and interactive Blazor charts for your web and mobile apps. The Ignite UI for Blazor charts deliver customizable features like animations, highlighting, annotations, drill-down, multiple layers, tooltips, and more, with an intuitive API, flexible theming, and minimal code to get started.

If your Blazor application needs to render millions of data points, advanced financial charts, or specialized chart types beyond what ApexCharts covers, the Infragistics integration is the recommended next step.