Doughnut Chart


Explore interactive Blazor Doughnut Chart demos with real-world examples. Learn how to visualize data, customize chart options, and implement data labels using the Blazor Doughnut Chart component.

API Documentation

Chart setup #

Before using any chart demo: install BlazorExpress.ChartJS 1.2.2, load Chart.js 4.4.1, chartjs-plugin-datalabels 2.2.0, and _content/BlazorExpress.ChartJS/blazorexpress.chartjs.js, then add @using BlazorExpress.ChartJS to your chart page or chart folder.

Follow the shared chart setup guide, the .NET 8 WebAssembly guide, or the .NET 8 Web App Server guide. For full chart component guidance and examples, visit chartjs.blazorexpress.com.

How it works #

The Doughnut Chart component provides a simple way to visualize categorical data as proportional segments of a circle.

How to use:
  1. Add the DoughnutChart component to your page.
  2. Define your data and labels using the chart's data model.
  3. Customize appearance and behavior using the Options property (e.g., colors, legend, tooltips).
  4. Bind your data and options to the component.
  5. Refer to the demo code below for a working example and further customization options.
This demo shows how to configure a basic doughnut chart, assign data, and adjust chart options for your scenario.
<DoughnutChart @ref="doughnutChart" Width="600" />

<div class="mt-5">
    <Button Color="ButtonColor.Primary" Size="ButtonSize.Small" @onclick="RandomizeAsync"> Randomize </Button>
    <Button Color="ButtonColor.Link" Size="ButtonSize.Small" @onclick="AddDatasetAsync"> Add Dataset </Button>
    <Button Color="ButtonColor.Info" Size="ButtonSize.Small" @onclick="AddDataAsync">Add Data</Button>
</div>

@code {
    private DoughnutChart doughnutChart = default!;
    private DoughnutChartOptions doughnutChartOptions = default!;
    private ChartData chartData = default!;
    private string[]? backgroundColors;

    private int datasetsCount = 0;
    private int dataLabelsCount = 0;

    private Random random = new();

    protected override void OnInitialized()
    {
        backgroundColors = ChartJsColorUtility.CategoricalTwelveColors;
        chartData = new ChartData { Labels = GetDefaultDataLabels(4), Datasets = GetDefaultDataSets(1) };

        doughnutChartOptions = new();
        doughnutChartOptions.Responsive = true;
        doughnutChartOptions.Plugins.Title!.Text = "2022 - Sales";
        doughnutChartOptions.Plugins.Title.Display = true;
    }

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
        {
            await doughnutChart.InitializeAsync(chartData, doughnutChartOptions);
        }
        await base.OnAfterRenderAsync(firstRender);
    }

    private async Task RandomizeAsync()
    {
        if (chartData is null || chartData.Datasets is null || !chartData.Datasets.Any()) return;

        var newDatasets = new List<IChartDataset>();

        foreach (var dataset in chartData.Datasets)
        {
            if (dataset is DoughnutChartDataset doughnutChartDataset
                && doughnutChartDataset is not null
                && doughnutChartDataset.Data is not null)
            {
                var count = doughnutChartDataset.Data.Count;

                var newData = new List<double?>();
                for (var i = 0; i < count; i++)
                {
                    newData.Add(random.Next(0, 100));
                }

                doughnutChartDataset.Data = newData;
                newDatasets.Add(doughnutChartDataset);
            }
        }

        chartData.Datasets = newDatasets;

        await doughnutChart.UpdateAsync(chartData, doughnutChartOptions);
    }

    private async Task AddDatasetAsync()
    {
        if (chartData is null || chartData.Datasets is null) return;

        var chartDataset = GetRandomDoughnutChartDataset();
        chartData = await doughnutChart.AddDatasetAsync(chartData, chartDataset, doughnutChartOptions);
    }

    private async Task AddDataAsync()
    {
        if (dataLabelsCount >= 12)
            return;

        if (chartData is null || chartData.Datasets is null)
            return;

        var data = new List<IChartDatasetData>();
        foreach (var dataset in chartData.Datasets)
        {
            if (dataset is DoughnutChartDataset doughnutChartDataset)
            {
                data.Add(new DoughnutChartDatasetData(doughnutChartDataset.Label, random.Next(0, 100), backgroundColors![dataLabelsCount]));
            }
        }

        chartData = await doughnutChart.AddDataAsync(chartData, GetNextDataLabel(), data);

        dataLabelsCount += 1;
    }

    #region Data Preparation

    private List<IChartDataset> GetDefaultDataSets(int numberOfDatasets)
    {
        var datasets = new List<IChartDataset>();

        for (var index = 0; index < numberOfDatasets; index++)
        {
            datasets.Add(GetRandomDoughnutChartDataset());
        }

        return datasets;
    }

    private DoughnutChartDataset GetRandomDoughnutChartDataset()
    {
        datasetsCount += 1;
        return new() { Label = $"Team {datasetsCount}", Data = GetRandomData(), BackgroundColor = GetRandomBackgroundColors() };
    }

    private List<double?> GetRandomData()
    {
        var data = new List<double?>();
        for (var index = 0; index < dataLabelsCount; index++)
        {
            data.Add(random.Next(0, 100));
        }

        return data;
    }

    private List<string> GetRandomBackgroundColors()
    {
        var colors = new List<string>();
        for (var index = 0; index < dataLabelsCount; index++)
        {
            colors.Add(backgroundColors![index]);
        }

        return colors;
    }

    private List<string> GetDefaultDataLabels(int numberOfLabels)
    {
        var labels = new List<string>();
        for (var index = 0; index < numberOfLabels; index++)
        {
            labels.Add(GetNextDataLabel());
            dataLabelsCount += 1;
        }

        return labels;
    }

    private string GetNextDataLabel() => $"Product {dataLabelsCount + 1}";

    private string GetNextDataBackgrounfColor() => backgroundColors![dataLabelsCount];

    #endregion  Data Preparation
}

Data labels #

The Doughnut Chart component supports data labels, allowing you to display values or category names directly on each segment of the chart.

How to use:
  1. Enable data labels by configuring the chart's plugin options, such as Options.Plugins.Datalabels.Display = true.
  2. You can customize the label content, formatting, and position using the available plugin settings.
  3. Assign your data and labels as usual to the chart's data model.
  4. Refer to the demo code below for a working example and further configuration options.
Data labels make it easier for users to interpret the chart by showing relevant information directly on each doughnut segment.
<DoughnutChart @ref="doughnutChart" Width="600" />

@code {
    private DoughnutChart doughnutChart = default!;
    private DoughnutChartOptions doughnutChartOptions = default!;
    private ChartData chartData = default!;
    private string[]? backgroundColors;

    private int datasetsCount = 0;
    private int dataLabelsCount = 0;

    private Random random = new();

    protected override void OnInitialized()
    {
        backgroundColors = ChartJsColorUtility.CategoricalTwelveColors;
        chartData = new ChartData { Labels = GetDefaultDataLabels(4), Datasets = GetDefaultDataSets(3) };

        doughnutChartOptions = new();
        doughnutChartOptions.Responsive = true;
        doughnutChartOptions.Plugins.Title!.Text = "2022 - Sales";
        doughnutChartOptions.Plugins.Title.Display = true;
    }

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
        {
            // pass the plugin name to enable the data labels
            await doughnutChart.InitializeAsync(chartData: chartData, chartOptions: doughnutChartOptions, plugins: new string[] { "ChartDataLabels" });
        }
        await base.OnAfterRenderAsync(firstRender);
    }

    private async Task RandomizeAsync()
    {
        if (chartData is null || chartData.Datasets is null || !chartData.Datasets.Any()) return;

        var newDatasets = new List<IChartDataset>();

        foreach (var dataset in chartData.Datasets)
        {
            if (dataset is DoughnutChartDataset doughnutChartDataset
                && doughnutChartDataset is not null
                && doughnutChartDataset.Data is not null)
            {
                var count = doughnutChartDataset.Data.Count;

                var newData = new List<double?>();
                for (var i = 0; i < count; i++)
                {
                    newData.Add(random.Next(0, 100));
                }

                doughnutChartDataset.Data = newData;
                newDatasets.Add(doughnutChartDataset);
            }
        }

        chartData.Datasets = newDatasets;

        await doughnutChart.UpdateAsync(chartData: chartData, chartOptions: doughnutChartOptions);
    }

    private async Task AddDataAsync()
    {
        if (dataLabelsCount >= 12)
            return;

        if (chartData is null || chartData.Datasets is null)
            return;

        var data = new List<IChartDatasetData>();
        foreach (var dataset in chartData.Datasets)
        {
            if (dataset is DoughnutChartDataset doughnutChartDataset)
            {
                data.Add(new DoughnutChartDatasetData(doughnutChartDataset.Label, random.Next(0, 100), backgroundColors![dataLabelsCount]));
            }
        }

        chartData = await doughnutChart.AddDataAsync(chartData, GetNextDataLabel(), data);

        dataLabelsCount += 1;
    }

    #region Data Preparation

    private List<IChartDataset> GetDefaultDataSets(int numberOfDatasets)
    {
        var datasets = new List<IChartDataset>();

        for (var index = 0; index < numberOfDatasets; index++)
        {
            var dataset = GetRandomDoughnutChartDataset();

            if (index == 0)
                dataset.Datalabels.Anchor = DataLabelAnchor.End;
            else if (index == numberOfDatasets - 1)
                dataset.Datalabels.Anchor = DataLabelAnchor.Start;
            else
                dataset.Datalabels.Anchor = DataLabelAnchor.Center;

            datasets.Add(dataset);
        }

        return datasets;
    }

    private DoughnutChartDataset GetRandomDoughnutChartDataset()
    {
        datasetsCount += 1;
        return new() { Label = $"Team {datasetsCount}", Data = GetRandomData(), BackgroundColor = GetRandomBackgroundColors() };
    }

    private List<double?> GetRandomData()
    {
        var data = new List<double?>();
        for (var index = 0; index < dataLabelsCount; index++)
        {
            data.Add(random.Next(0, 100));
        }

        return data;
    }

    private List<string> GetRandomBackgroundColors()
    {
        var colors = new List<string>();
        for (var index = 0; index < dataLabelsCount; index++)
        {
            colors.Add(backgroundColors![index]);
        }

        return colors;
    }

    private List<string> GetDefaultDataLabels(int numberOfLabels)
    {
        var labels = new List<string>();
        for (var index = 0; index < numberOfLabels; index++)
        {
            labels.Add(GetNextDataLabel());
            dataLabelsCount += 1;
        }

        return labels;
    }

    private string GetNextDataLabel() => $"Product {dataLabelsCount + 1}";

    private string GetNextDataBackgrounfColor() => backgroundColors![dataLabelsCount];

    #endregion  Data Preparation
}
DO YOU KNOW?
This demo website is built using the BlazorExpress.Bulma library and published on the Azure Web App. See our source code on GitHub.