Blazor-ApexCharts is a Blazor chart component that renders ApexCharts from strongly typed C#. You declare <ApexChart> in Razor, bind it to your own model with lambda accessors, and configure it with ApexChartOptions<T> rather than a JavaScript options object. It installs as a single NuGet package that carries its own JavaScript and CSS, so there is no npm, no bundler and no script tag.

dotnet add package Blazor-ApexCharts
@using ApexCharts
@rendermode InteractiveServer

<ApexChart TItem="Sale" Title="Revenue by month">
    <ApexPointSeries TItem="Sale"
                     Items="sales"
                     Name="Revenue"
                     SeriesType="SeriesType.Bar"
                     XValue="e => e.Month"
                     YValue="e => e.Revenue" />
</ApexChart>

@code {
    private List<Sale> sales = new()
    {
        new Sale { Month = "Jan", Revenue = 12000 },
        new Sale { Month = "Feb", Revenue = 43000 },
        new Sale { Month = "Mar", Revenue = 31000 }
    };

    public class Sale
    {
        public string Month { get; set; }
        public decimal Revenue { get; set; }
    }
}

That is a complete, working chart. Version 7.0.0 multi-targets .NET 8, 9 and 10, and runs in Blazor Server, Blazor WebAssembly, WinForms and WPF. .NET MAUI uses the companion package Blazor-ApexCharts-MAUI.

Curve = Curve.Smooth

Configuration That the Compiler Checks

ApexChartOptions<T> is a real generic type, not a dictionary of strings. Theme.Mode takes a Mode enum, Stroke.Curve takes a Curve, and a misspelled option name is a build error rather than a key that is silently ignored at runtime. The chart beside this flips between Curve.Smooth and Curve.Straight, which in C# is a one-word change the compiler validates.


Twelve Chart Types from One Enum

The same markup and the same bound collection produce a bar, line, area or scatter chart: change SeriesType and nothing else. The enum covers Area, Bar, Donut, Heatmap, Line, Pie, PolarArea, Radar, RadialBar, Scatter, Treemap and RangeArea, with dedicated series components for the shapes that need different data.

SeriesType="SeriesType.Bar"


Aggregate Rows Without Reshaping Your Data

Single-dimension charts pair SeriesType with YAggregate, so a list of orders becomes gross value per country without you writing a grouping step first. The lambda runs over your own model: YAggregate="@(e => e.Sum(e => e.GrossValue))". Your query stays the shape your API returns.


Explicit Updates, Not Implicit Re-renders

Hold the component with @ref, change the bound collection, then call UpdateSeriesAsync. Coming from React or Vue this is the surprise: mutating the list does not redraw the chart on its own. The upside is that you control exactly when a redraw happens and whether it animates.

await chart.UpdateSeriesAsync(animate: true)

One Package, No Toolchain

The JavaScript and CSS ship inside the NuGet package, served from _content/Blazor-ApexCharts/. No npm, bundler, CDN or script tag.

Strongly Typed Options

ApexChartOptions<T> with typed properties and enums throughout, so option names and values are checked at build time.

Lambda Data Accessors

XValue, YValue and YAggregate are lambdas over your own model rather than field-name strings.

Runtime Updates

UpdateSeriesAsync and UpdateOptionsAsync redraw on demand, with control over animation and synced charts.

Server and WebAssembly

Async IJSRuntime interop throughout, so neither Blazor hosting model is a special case.

.NET MAUI

The companion Blazor-ApexCharts-MAUI package covers android, ios and maccatalyst.

Global Theming

An optional scoped IApexChartService carries global options, palettes and locales across every chart on screen.

MIT Wrapper, No Key for Charting

The NuGet package is MIT. Every chart type and standard option works with no licence key.

Add a Chart to a Blazor App

Four steps, and only the third involves any chart-specific thinking. Start with the package:

dotnet add package Blazor-ApexCharts

For .NET MAUI, install the companion package instead:

dotnet add package Blazor-ApexCharts-MAUI

Add the namespace to _Imports.razor. Note that the namespace is ApexCharts even though the package is Blazor-ApexCharts:

@using ApexCharts

Registering IApexChartService is optional for a single chart, and worth having as soon as you want shared theming, locales, or a handle on the chart instances on screen:

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

On MAUI the equivalent is services.AddApexChartsMaui().

Why Does My Blazor Chart Render Blank?

Because the component is rendering statically and the JavaScript interop never runs.

From .NET 8, Blazor Web Apps render statically by default, and a component that needs JS interop has to opt into interactivity. Set the render mode on the page or the component:

@rendermode InteractiveServer

InteractiveWebAssembly and InteractiveAuto work equally well. There is no error and nothing in the browser console, which is why this costs people an afternoon. If a chart renders as empty space, check this first.

Configure Chart Options in C#

Through ApexChartOptions<T>, which mirrors the JavaScript options object as typed C# properties and enums.

<ApexChart TItem="Sale" Title="Revenue" Options="options">
    <ApexPointSeries TItem="Sale" Items="sales" Name="Revenue"
                     SeriesType="SeriesType.Line"
                     XValue="e => e.Month"
                     YValue="e => e.Revenue" />
</ApexChart>

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

Curve.Smooth and Mode.Dark are enums, and the option properties are typed, so a misspelled option name or an invalid value is a build error. That is the substantive difference from configuring the same chart in JavaScript, where an unrecognised option key is silently ignored at runtime.

Options that accept either one value or a list are modelled as a ValueOrList<T> with implicit conversions both ways, so you write the singular form and it still compiles. Stroke.Curve is typed CurveSelections, which is why Curve = Curve.Smooth and a list of curves are both valid.

Each chart instance needs its own ApexChartOptions instance. Options objects cannot be shared between charts.

Choosing a Chart Type

Change the SeriesType enum on the series. It covers twelve types: Area, Bar, Donut, Heatmap, Line, Pie, PolarArea, Radar, RadialBar, Scatter, Treemap and RangeArea.

Pie, donut, polar area and radial bar are single dimensional, so they normally pair SeriesType with YAggregate instead of YValue, collapsing many rows into one value per category:

<ApexChart TItem="Order" Title="Gross value by country">
    <ApexPointSeries TItem="Order"
                     Items="orders"
                     Name="Gross Value"
                     SeriesType="SeriesType.Donut"
                     XValue="@(e => e.Country)"
                     YAggregate="@(e => e.Sum(e => e.GrossValue))"
                     OrderByDescending="e => e.Y"
                     ShowDataLabels />
</ApexChart>

Chart types that need a different data shape have their own series components rather than a SeriesType value: <ApexBubbleSeries>, <ApexCandleSeries>, <ApexBoxPlotSeries>, <ApexRangeSeries>, <ApexRangeAreaSeries> and <ApexViolinSeries>. There is also a standalone <ApexGauge> component.

Update a Chart with New Data

Hold a reference with @ref and call UpdateSeriesAsync() after mutating the underlying collection. This is the part that surprises people coming from React or Vue: mutating the list does not re-render the chart on its own.

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

<ApexChart TItem="Sale" Title="Revenue" @ref="chart">
    <ApexPointSeries TItem="Sale" Items="sales" Name="Revenue"
                     SeriesType="SeriesType.Line"
                     XValue="e => e.Month"
                     YValue="e => e.Revenue" />
</ApexChart>

@code {
    private List<Sale> sales = new();
    private ApexChart<Sale> chart;

    private async Task Reload()
    {
        sales = await LoadSalesAsync();
        await chart.UpdateSeriesAsync(animate: true);
    }
}

UpdateSeriesAsync(bool animate = true) takes a single optional flag. UpdateOptionsAsync is the equivalent for changing options at runtime, and its signature is wider: UpdateOptionsAsync(bool redrawPaths, bool animate, bool updateSyncedCharts, ZoomOptions zoom = null). The first three are required, so there is no one-argument form.

One constraint worth knowing before you design your model: ApexChart<TItem> is declared where TItem : class, so the type you bind must be a reference type. A struct or record struct will not compile as TItem.

When to Use Something Else

  • You need charts rendered on the server with no browser. This is a client-side engine driven through JS interop. A headless PNG report pipeline is not its job.
  • Your team already lives in a JavaScript build. Use apexcharts directly. The value of this package is staying in C#, and if you are not staying in C# it is a layer you do not need.
  • You need the interaction modules and cannot licence them. The charts are complete without a key, but undo and redo, crossfilter, measure and storyboard are not.

Blazor Chart Component FAQ

What is Blazor-ApexCharts?

Blazor-ApexCharts is a Blazor wrapper for ApexCharts.js that exposes the chart configuration surface as strongly typed C# classes and Razor components. It runs in Blazor Server, Blazor WebAssembly, WinForms and WPF, and in .NET MAUI through a companion package.

How do I install the Blazor chart component?

Run dotnet add package Blazor-ApexCharts, then add @using ApexCharts to your _Imports.razor. No npm, bundler or script tag is involved: the JavaScript and CSS ship inside the package and are served from _content/Blazor-ApexCharts/.

Which .NET versions does Blazor-ApexCharts support?

Version 7.0.0 multi-targets .NET 8, .NET 9 and .NET 10. The companion MAUI package targets .NET 9 for android, ios and maccatalyst.

Why does my Blazor chart render blank?

Almost always the render mode. From .NET 8, Blazor Web Apps render statically by default, so a component that needs JavaScript interop must opt in. Set the host page or component to InteractiveServer, InteractiveWebAssembly or InteractiveAuto, or the interop never runs and there is no console error.

Do I need a license key for Blazor charts?

Not for charting. Every chart type and every standard option works with no key and no revenue threshold. Only the seven premium interaction modules, which are undo and redo, perspectives, linked views with crossfilter, ink annotations, measure, context menu and storyboard, run in trial mode with a watermark until a key is applied.

How is Blazor-ApexCharts licensed?

The Blazor-ApexCharts wrapper package on NuGet is MIT licensed. MIT covers the wrapper. The ApexCharts engine it loads is a separate work under its own terms.

How do I refresh a Blazor chart with new data?

Hold the component with @ref and call UpdateSeriesAsync after changing the bound collection. Its signature is UpdateSeriesAsync(bool animate = true). UpdateOptionsAsync does the same for options, and takes redrawPaths, animate and updateSyncedCharts as required arguments.

Can I use ApexCharts in .NET MAUI?

Yes, through the Blazor-ApexCharts-MAUI package, registered with AddApexChartsMaui instead of AddApexCharts.

Ready to chart in C#?

One dotnet add package, one @using, and an interactive render mode. The setup guide walks the rest.

Browse chart demos