From 73c87e345e0527a0973fd8fcc159a526565a9db8 Mon Sep 17 00:00:00 2001 From: Argo Zhang Date: Thu, 23 Jul 2026 17:04:13 +0800 Subject: [PATCH 1/2] feat(Chart): add Total/Tooltip/CategoryLabel format parameter --- .../Components/Samples/Charts/Bar.razor | 112 ++++-------------- .../Components/Samples/Charts/Bar.razor.cs | 38 +++--- .../Components/Samples/Charts/Bar.razor.js | 63 ---------- src/BootstrapBlazor.Server/Locales/en-US.json | 21 ++-- src/BootstrapBlazor.Server/Locales/zh-CN.json | 21 ++-- 5 files changed, 65 insertions(+), 190 deletions(-) delete mode 100644 src/BootstrapBlazor.Server/Components/Samples/Charts/Bar.razor.js diff --git a/src/BootstrapBlazor.Server/Components/Samples/Charts/Bar.razor b/src/BootstrapBlazor.Server/Components/Samples/Charts/Bar.razor index e3d350a7195..0423c133224 100644 --- a/src/BootstrapBlazor.Server/Components/Samples/Charts/Bar.razor +++ b/src/BootstrapBlazor.Server/Components/Samples/Charts/Bar.razor @@ -77,49 +77,27 @@ - +
  • @((MarkupString)Localizer["CustomTooltipLi1"].Value)

    -
    <Chart ChartType="ChartType.Bar" OnInitAsync="() => OnInit(false)" Id="@@CustomTooltipId" />
    +
    <Chart ChartType="ChartType.Bar" OnInitAsync="OnInitCustomTooltip" />
  • @((MarkupString)Localizer["CustomTooltipLi2"].Value)

    -
    import '../../../_content/BootstrapBlazor.Chart/Components/Chart/Chart.razor.js'
    -
    -export function customTooltip(id) {
    -    // chart.js documentation: https://www.chartjs.org/docs/latest/configuration/tooltip.html
    -    const chart = BootstrapBlazor.Chart;
    -    chart.setOptionsById(id, {
    -        options: {
    -            plugins: {
    -                tooltip: {
    -                    callbacks: {
    -                        title: tooltipItems => `Day ${tooltipItems[0].label}`,
    -                        label: context => ` ${context.dataset.label}: ${context.parsed.y} units`
    -                    }
    -                }
    -            }
    -        }
    -    });
    -}
    -
  • -
  • -

    @((MarkupString)Localizer["CustomTooltipLi3"].Value)

    -
    protected override async Task InvokeInitAsync()
    +                
    private Task<ChartDataSource> OnInitCustomTooltip()
     {
    -    await InvokeVoidAsync("customTooltip", CustomTooltipId);
    +    var ds = OnInit(false).Result;
    +    ds.Options.TooltipTitleFormatter = "Day {label}";
    +    ds.Options.TooltipLabelFormatter = " {datasetLabel}: {value} units";
    +    return Task.FromResult(ds);
     }
  • - +
  • @((MarkupString)Localizer["CustomCategoryLabelLi1"].Value)

    -
    <Chart ChartType="ChartType.Bar" OnInitAsync="() => OnInit(false)" Id="@@CustomCategoryLabelId" />
    +
    <Chart ChartType="ChartType.Bar" OnInitAsync="OnInitCustomCategoryLabel" />
  • @((MarkupString)Localizer["CustomCategoryLabelLi2"].Value)

    -
    import '../../../_content/BootstrapBlazor.Chart/Components/Chart/Chart.razor.js'
    -
    -export function customCategoryLabel(id) {
    -    // chart.js documentation: https://www.chartjs.org/docs/latest/axes/labelling.html
    -    const chart = BootstrapBlazor.Chart;
    -    chart.setOptionsById(id, {
    -        options: {
    -            scales: {
    -                x: {
    -                    ticks: {
    -                        callback: function (value) {
    -                            return `Day ${this.getLabelForValue(value)}`;
    -                        }
    -                    }
    -                }
    -            }
    -        }
    -    });
    -}
    -
  • -
  • -

    @((MarkupString)Localizer["CustomCategoryLabelLi3"].Value)

    -
    protected override async Task InvokeInitAsync()
    +                
    private Task<ChartDataSource> OnInitCustomCategoryLabel()
     {
    -    await InvokeVoidAsync("customCategoryLabel", CustomCategoryLabelId);
    +    var ds = OnInit(false).Result;
    +    ds.Options.CategoryLabelFormatter = "Day {label}";
    +    return Task.FromResult(ds);
     }
  • - +
    diff --git a/src/BootstrapBlazor.Server/Components/Samples/Charts/Bar.razor.cs b/src/BootstrapBlazor.Server/Components/Samples/Charts/Bar.razor.cs index c5f1603d696..497c8922e82 100644 --- a/src/BootstrapBlazor.Server/Components/Samples/Charts/Bar.razor.cs +++ b/src/BootstrapBlazor.Server/Components/Samples/Charts/Bar.razor.cs @@ -8,18 +8,11 @@ namespace BootstrapBlazor.Server.Components.Samples.Charts; /// /// Bar 图表示例 /// -[JSModuleAutoLoader("Samples/Charts/Bar.razor.js", JSObjectReference = true)] public partial class Bar { private int _barDatasetCount = 2; private int _barDataCount = 7; - private string CustomTooltipId => $"custom_tooltip_{Id}"; - - private string CustomCategoryLabelId => $"custom_category_label_{Id}"; - - private string TotalDataLabelId => $"total_data_label_{Id}"; - private int BarDatasetCount { get; set; } = 2; private int BarDataCount { get; set; } = 7; @@ -44,16 +37,6 @@ protected override void OnAfterRender(bool firstRender) } } - /// - /// - /// - protected override async Task InvokeInitAsync() - { - await InvokeVoidAsync("customTooltip", CustomTooltipId); - await InvokeVoidAsync("customCategoryLabel", CustomCategoryLabelId); - await InvokeVoidAsync("customTotalDataLabel", TotalDataLabelId); - } - private Task OnAfterInit() { Logger.Log("Bar initialization is complete"); @@ -256,6 +239,12 @@ private Task OnInitTotalDataLabel() ds.Options.Title = "Stacked total"; ds.Options.ShowDataLabel = true; ds.Options.ShowTotalDataLabel = true; + ds.Options.TotalDataLabelFormatter = "Total: {total}"; + ds.Options.TotalDataLabelColor = "#fff"; + ds.Options.TotalDataLabelBackgroundColor = "rgb(75, 192, 192)"; + ds.Options.TotalDataLabelBorderRadius = 4; + ds.Options.TotalDataLabelPadding = 6; + ds.Options.TotalDataLabelFontWeight = "bold"; ds.Options.Anchor = ChartDataLabelPosition.Center; ds.Options.X.Title = "name"; ds.Options.Y.Title = "Numerical value"; @@ -275,6 +264,21 @@ private Task OnInitTotalDataLabel() return Task.FromResult(ds); } + private Task OnInitCustomTooltip() + { + var ds = OnInit(false).Result; + ds.Options.TooltipTitleFormatter = "Day {label}"; + ds.Options.TooltipLabelFormatter = " {datasetLabel}: {value} units"; + return Task.FromResult(ds); + } + + private Task OnInitCustomCategoryLabel() + { + var ds = OnInit(false).Result; + ds.Options.CategoryLabelFormatter = "Day {label}"; + return Task.FromResult(ds); + } + private Task OnInitAutoSkip(bool autoSkip) { var ds = new ChartDataSource(); diff --git a/src/BootstrapBlazor.Server/Components/Samples/Charts/Bar.razor.js b/src/BootstrapBlazor.Server/Components/Samples/Charts/Bar.razor.js deleted file mode 100644 index 9b75a068b1a..00000000000 --- a/src/BootstrapBlazor.Server/Components/Samples/Charts/Bar.razor.js +++ /dev/null @@ -1,63 +0,0 @@ -import '../../../_content/BootstrapBlazor.Chart/Components/Chart/Chart.razor.js' - -export function customCategoryLabel(id) { - // chart.js documentation: https://www.chartjs.org/docs/latest/axes/labelling.html - const chart = BootstrapBlazor.Chart; - chart.setOptionsById(id, { - options: { - scales: { - x: { - ticks: { - callback: function (value) { - return `Day ${this.getLabelForValue(value)}`; - } - } - } - } - } - }); -} - -export function customTotalDataLabel(id) { - // chartjs-plugin-datalabels documentation: https://chartjs-plugin-datalabels.netlify.app/guide/options.html - const chart = BootstrapBlazor.Chart; - chart.setOptionsById(id, { - options: { - plugins: { - datalabels: { - labels: { - total: { - color: '#fff', - backgroundColor: 'rgb(75, 192, 192)', - borderRadius: 4, - padding: { top: 2, bottom: 2, left: 6, right: 6 }, - font: { weight: 'bold' }, - formatter: (value, context) => { - const total = context.chart.data.datasets.reduce( - (sum, v, index) => context.chart.isDatasetVisible(index) ? sum + (Number(v.data[context.dataIndex]) || 0) : sum, 0); - return `Total: ${total}`; - } - } - } - } - } - } - }); -} - -export function customTooltip(id) { - // chart.js documentation: https://www.chartjs.org/docs/latest/configuration/tooltip.html - const chart = BootstrapBlazor.Chart; - chart.setOptionsById(id, { - options: { - plugins: { - tooltip: { - callbacks: { - title: tooltipItems => `Day ${tooltipItems[0].label}`, - label: context => ` ${context.dataset.label}: ${context.parsed.y} units` - } - } - } - } - }); -} diff --git a/src/BootstrapBlazor.Server/Locales/en-US.json b/src/BootstrapBlazor.Server/Locales/en-US.json index 165f30d1d63..d82928c3fa6 100644 --- a/src/BootstrapBlazor.Server/Locales/en-US.json +++ b/src/BootstrapBlazor.Server/Locales/en-US.json @@ -1265,10 +1265,9 @@ "BarStackedShowDataLabelIntro": "When ShowDataLabel is enabled in stacked mode, the position of the data label is controlled by the Anchor property. The default End displays it at the top of the segment, and Center displays it in the center of the segment. Segments with a value of 0 do not draw data labels to avoid overlapping with adjacent segment labels. In this example, the top segment of Bob has a value of 0, so only the lower segment's data label is displayed", "BarStackedShowDataLabelTitle": "Stacked Data Label", "BarStackedTitle": "Stacked", - "BarTotalDataLabelIntro": "In stacked mode, set the ShowTotalDataLabel property to display the total data label above each bar. The total value is automatically recalculated when a dataset is hidden by clicking the legend. In this example, the total label is customized by the client script setOptionsById: the total text is formatted as Total: {X}, and the text color, background color, border radius, padding and font style are customized", - "BarTotalDataLabelLi1": "Set the Id parameter of the Chart component", - "BarTotalDataLabelLi2": "Create a client JavaScript script, override the formatter callback of the total label by the setOptionsById method to customize the total text, and customize the label style by the color backgroundColor borderRadius padding font properties", - "BarTotalDataLabelLi3": "Override the base class method InvokeInitAsync and call the client script by await InvokeVoidAsync(\"customTotalDataLabel\", TotalDataLabelId)", + "BarTotalDataLabelIntro": "In stacked mode, set the ShowTotalDataLabel property to display the total data label above each bar. The total value is automatically recalculated when a dataset is hidden by clicking the legend. In this example, the total text, text color, background color, border radius, padding, and font style are customized by ChartDataSource.Options", + "BarTotalDataLabelLi1": "Set the OnInitAsync delegate of the Chart component", + "BarTotalDataLabelLi2": "Set ShowTotalDataLabel, TotalDataLabelFormatter, and total label style properties in ChartDataSource.Options", "BarTotalDataLabelTitle": "Stacked Total Label", "BarTwoYAxesIntro": "Show secondary Y axis: alignment, title and data group", "BarTwoYAxesTitle": "Double Y axis", @@ -1282,15 +1281,13 @@ "BarTypeRemoveData": "Remove data", "BarTypeRemoveDataSet": "Remove dataset", "BarTypeTitle": "Bar graph", - "CustomCategoryLabelIntro": "Customize the category label text below each bar on the x-axis by client script", - "CustomCategoryLabelLi1": "Set the Id parameter of the Chart component", - "CustomCategoryLabelLi2": "Create a client JavaScript script, set the ticks callback of the x-axis by setOptionsById method. In this example, the prefix Day is added to each category label", - "CustomCategoryLabelLi3": "Override the base class method InvokeInitAsync and call the client script by await InvokeVoidAsync(\"customCategoryLabel\", CustomCategoryLabelId)", + "CustomCategoryLabelIntro": "Customize the category label text below each bar on the x-axis by ChartDataSource.Options", + "CustomCategoryLabelLi1": "Set the OnInitAsync delegate of the Chart component", + "CustomCategoryLabelLi2": "Set CategoryLabelFormatter in ChartDataSource.Options to format category labels. In this example, the prefix Day is added to each category label", "CustomCategoryLabelTitle": "Custom Category Label", - "CustomTooltipIntro": "Customize the hover Tooltip text of the bar chart by client script", - "CustomTooltipLi1": "Set the Id parameter of the Chart component", - "CustomTooltipLi2": "Create a client JavaScript script, set the tooltip callbacks by setOptionsById method. In this example, the title and label text are customized", - "CustomTooltipLi3": "Override the base class method InvokeInitAsync and call the client script by await InvokeVoidAsync(\"customTooltip\", CustomTooltipId)", + "CustomTooltipIntro": "Customize the hover Tooltip text of the bar chart by ChartDataSource.Options", + "CustomTooltipLi1": "Set the OnInitAsync delegate of the Chart component", + "CustomTooltipLi2": "Set TooltipTitleFormatter and TooltipLabelFormatter in ChartDataSource.Options to format the title and label text", "CustomTooltipTitle": "Custom Tooltip" }, "BootstrapBlazor.Server.Components.Samples.Charts.Bubble": { diff --git a/src/BootstrapBlazor.Server/Locales/zh-CN.json b/src/BootstrapBlazor.Server/Locales/zh-CN.json index 24f44f78555..51e12289ee4 100644 --- a/src/BootstrapBlazor.Server/Locales/zh-CN.json +++ b/src/BootstrapBlazor.Server/Locales/zh-CN.json @@ -1265,10 +1265,9 @@ "BarStackedShowDataLabelIntro": "堆叠模式开启 ShowDataLabel 时,通过 Anchor 属性控制数据标签位置,默认 End 显示在分段顶部,设置为 Center 时显示在分段中间;值为 0 的分段不绘制数据标签,避免与相邻分段标签重叠。本例中 Bob 顶部分段值为 0,仅显示下方分段的数据标签", "BarStackedShowDataLabelTitle": "堆叠图数据标签", "BarStackedTitle": "堆砌排列", - "BarTotalDataLabelIntro": "堆叠模式通过设置 ShowTotalDataLabel 属性,在每个柱条顶部显示总计数据标签,点击图例隐藏数据集时总计值自动重新计算。本例中通过客户端脚本 setOptionsById 自定义 total 标签,将总计文本自定义为 Total: {X} 格式,并自定义了文字颜色、背景色、圆角、内边距与字体样式", - "BarTotalDataLabelLi1": "Chart 组件设置 Id 参数", - "BarTotalDataLabelLi2": "创建客户端 JavaScript 脚本,通过 setOptionsById 方法覆盖 total 标签的 formatter 回调自定义总计文本,并通过 color backgroundColor borderRadius padding font 等属性自定义标签样式", - "BarTotalDataLabelLi3": "本例中重载基类方法 InvokeInitAsync 通过 await InvokeVoidAsync(\"customTotalDataLabel\", TotalDataLabelId) 语句调用客户端脚本", + "BarTotalDataLabelIntro": "堆叠模式通过设置 ShowTotalDataLabel 属性,在每个柱条顶部显示总计数据标签,点击图例隐藏数据集时总计值自动重新计算。本例中通过 ChartDataSource.Options 自定义总计文本、文字颜色、背景色、圆角、内边距与字体样式", + "BarTotalDataLabelLi1": "Chart 组件设置 OnInitAsync 委托方法", + "BarTotalDataLabelLi2": "在 ChartDataSource.Options 中设置 ShowTotalDataLabelTotalDataLabelFormatter 以及总计标签样式属性", "BarTotalDataLabelTitle": "堆叠总计标签", "BarTwoYAxesIntro": "显示第二Y轴:对齐方式,标题和对应数据组", "BarTwoYAxesTitle": "双Y轴", @@ -1282,15 +1281,13 @@ "BarTypeRemoveData": "移除数据", "BarTypeRemoveDataSet": "移除数据集", "BarTypeTitle": "Bar 图", - "CustomCategoryLabelIntro": "自定义柱状图 X 轴每个柱子下方的分类标签显示文本,需要使用客户端脚本设置", - "CustomCategoryLabelLi1": "Chart 组件设置 Id 参数", - "CustomCategoryLabelLi2": "创建客户端 JavaScript 脚本,通过 setOptionsById 方法设置 X 轴 ticks 回调函数,本例中为每个分类标签增加了 Day 前缀", - "CustomCategoryLabelLi3": "本例中重载基类方法 InvokeInitAsync 通过 await InvokeVoidAsync(\"customCategoryLabel\", CustomCategoryLabelId) 语句调用客户端脚本", + "CustomCategoryLabelIntro": "通过 ChartDataSource.Options 自定义柱状图 X 轴每个柱子下方的分类标签显示文本", + "CustomCategoryLabelLi1": "Chart 组件设置 OnInitAsync 委托方法", + "CustomCategoryLabelLi2": "在 ChartDataSource.Options 中设置 CategoryLabelFormatter 格式化分类标签,本例中为每个分类标签增加了 Day 前缀", "CustomCategoryLabelTitle": "自定义分类标签", - "CustomTooltipIntro": "自定义柱状图悬停 Tooltip 显示文本,需要使用客户端脚本设置", - "CustomTooltipLi1": "Chart 组件设置 Id 参数", - "CustomTooltipLi2": "创建客户端 JavaScript 脚本,通过 setOptionsById 方法设置 tooltip 回调函数,本例中自定义了 titlelabel 显示文本", - "CustomTooltipLi3": "本例中重载基类方法 InvokeInitAsync 通过 await InvokeVoidAsync(\"customTooltip\", CustomTooltipId) 语句调用客户端脚本", + "CustomTooltipIntro": "通过 ChartDataSource.Options 自定义柱状图悬停 Tooltip 显示文本", + "CustomTooltipLi1": "Chart 组件设置 OnInitAsync 委托方法", + "CustomTooltipLi2": "在 ChartDataSource.Options 中设置 TooltipTitleFormatterTooltipLabelFormatter 格式化 titlelabel 显示文本", "CustomTooltipTitle": "自定义 Tooltip" }, "BootstrapBlazor.Server.Components.Samples.Charts.Bubble": { From 1930abf30258aa158cf96db489471dd5d2876452 Mon Sep 17 00:00:00 2001 From: Argo Zhang Date: Thu, 23 Jul 2026 17:04:22 +0800 Subject: [PATCH 2/2] chore: bump version 10.0.7 --- src/BootstrapBlazor.Server/BootstrapBlazor.Server.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/BootstrapBlazor.Server/BootstrapBlazor.Server.csproj b/src/BootstrapBlazor.Server/BootstrapBlazor.Server.csproj index 1b00047b168..c95d0f8ac18 100644 --- a/src/BootstrapBlazor.Server/BootstrapBlazor.Server.csproj +++ b/src/BootstrapBlazor.Server/BootstrapBlazor.Server.csproj @@ -29,7 +29,7 @@ - +