+ Selected: @selectedChartItem.DatasetLabel (dataset @selectedChartItem.DatasetIndex), @selectedChartItem.Label (index @selectedChartItem.Index), value @selectedChartItem.Value
+
+}
Randomize
@@ -12,6 +19,7 @@
private BarChart barChart = default!;
private BarChartOptions barChartOptions = default!;
private ChartData chartData = default!;
+ private ChartClickEventArgs? selectedChartItem;
private int datasetsCount = 0;
private int labelsCount = 0;
@@ -33,6 +41,12 @@
await base.OnAfterRenderAsync(firstRender);
}
+ private Task HandleClickAsync(ChartClickEventArgs eventArgs)
+ {
+ selectedChartItem = eventArgs;
+ return Task.CompletedTask;
+ }
+
private async Task RandomizeAsync()
{
if (chartData is null || chartData.Datasets is null || !chartData.Datasets.Any()) return;
diff --git a/BlazorExpress.ChartJS.Demo.RCL/Pages/Demos/BarChart/BarChart_Demo_11_Click_Event.razor b/BlazorExpress.ChartJS.Demo.RCL/Pages/Demos/BarChart/BarChart_Demo_11_Click_Event.razor
new file mode 100644
index 00000000..60f97778
--- /dev/null
+++ b/BlazorExpress.ChartJS.Demo.RCL/Pages/Demos/BarChart/BarChart_Demo_11_Click_Event.razor
@@ -0,0 +1,47 @@
+
+
+@if (selectedChartItem is not null)
+{
+
+ Selected: @selectedChartItem.DatasetLabel (dataset @selectedChartItem.DatasetIndex), @selectedChartItem.Label (index @selectedChartItem.Index), value @selectedChartItem.Value
+
+}
+
+@code {
+ private BarChart barChart = default!;
+ private BarChartOptions barChartOptions = default!;
+ private ChartData chartData = default!;
+ private ChartClickEventArgs? selectedChartItem;
+
+ protected override void OnInitialized()
+ {
+ chartData = new ChartData
+ {
+ Labels = new List
{ "January", "February", "March" },
+ Datasets = new List
+ {
+ new BarChartDataset
+ {
+ Label = "Orders",
+ Data = new List { 45, 68, 54 },
+ BackgroundColor = new List { "#36A2EB" },
+ },
+ },
+ };
+ barChartOptions = new BarChartOptions { Responsive = true };
+ }
+
+ protected override async Task OnAfterRenderAsync(bool firstRender)
+ {
+ if (firstRender)
+ await barChart.InitializeAsync(chartData, barChartOptions);
+
+ await base.OnAfterRenderAsync(firstRender);
+ }
+
+ private Task HandleClickAsync(ChartClickEventArgs eventArgs)
+ {
+ selectedChartItem = eventArgs;
+ return Task.CompletedTask;
+ }
+}
diff --git a/BlazorExpress.ChartJS.Demo.RCL/Pages/Demos/BubbleChart/BubbleChartDocumentation.razor b/BlazorExpress.ChartJS.Demo.RCL/Pages/Demos/BubbleChart/BubbleChartDocumentation.razor
index dc7e3963..748e3325 100644
--- a/BlazorExpress.ChartJS.Demo.RCL/Pages/Demos/BubbleChart/BubbleChartDocumentation.razor
+++ b/BlazorExpress.ChartJS.Demo.RCL/Pages/Demos/BubbleChart/BubbleChartDocumentation.razor
@@ -34,6 +34,13 @@
+
+
+ Set the OnClick callback to react when a bubble is selected. The callback receives ChartClickEventArgs with the dataset, point index, and raw value; the demo displays the selected item below the chart.
+
+
+
+
@code {
private const string pageUrl = DemoRouteConstants.Demos_BubbleChart;
private const string pageTitle = "Bubble Chart";
diff --git a/BlazorExpress.ChartJS.Demo.RCL/Pages/Demos/BubbleChart/BubbleChart_Demo_02_Click_Event.razor b/BlazorExpress.ChartJS.Demo.RCL/Pages/Demos/BubbleChart/BubbleChart_Demo_02_Click_Event.razor
new file mode 100644
index 00000000..3180aa8c
--- /dev/null
+++ b/BlazorExpress.ChartJS.Demo.RCL/Pages/Demos/BubbleChart/BubbleChart_Demo_02_Click_Event.razor
@@ -0,0 +1,54 @@
+
+
+@if (selectedChartItem is not null)
+{
+
+ Selected: @selectedChartItem.DatasetLabel (dataset @selectedChartItem.DatasetIndex), @selectedChartItem.Label (index @selectedChartItem.Index), value @selectedChartItem.Value
+
+}
+
+@code {
+ private BubbleChart bubbleChart = default!;
+ private BubbleChartOptions bubbleChartOptions = default!;
+ private ChartData chartData = default!;
+ private ChartClickEventArgs? selectedChartItem;
+
+ protected override void OnInitialized()
+ {
+ chartData = new ChartData
+ {
+ Labels = new List { "January", "February", "March" },
+ Datasets = new List
+ {
+ new BubbleChartDataset
+ {
+ Label = "Projects",
+ Data = new List
+ {
+ new(10, 20, 8),
+ new(15, 12, 12),
+ new(8, 25, 6),
+ },
+ BackgroundColor = new List { "rgba(255, 99, 132, 0.5)" },
+ BorderColor = new List { "rgb(255, 99, 132)" },
+ BorderWidth = 1,
+ },
+ },
+ };
+ bubbleChartOptions = new BubbleChartOptions { Responsive = true };
+ }
+
+ protected override async Task OnAfterRenderAsync(bool firstRender)
+ {
+ if (firstRender)
+ await bubbleChart.InitializeAsync(chartData, bubbleChartOptions);
+
+ await base.OnAfterRenderAsync(firstRender);
+ }
+
+ private Task HandleClickAsync(ChartClickEventArgs eventArgs)
+ {
+ selectedChartItem = eventArgs;
+ return Task.CompletedTask;
+ }
+}
diff --git a/BlazorExpress.ChartJS.Demo.RCL/Pages/Demos/DoughnutChart/DoughnutChartDocumentation.razor b/BlazorExpress.ChartJS.Demo.RCL/Pages/Demos/DoughnutChart/DoughnutChartDocumentation.razor
index d5a939dd..1228666d 100644
--- a/BlazorExpress.ChartJS.Demo.RCL/Pages/Demos/DoughnutChart/DoughnutChartDocumentation.razor
+++ b/BlazorExpress.ChartJS.Demo.RCL/Pages/Demos/DoughnutChart/DoughnutChartDocumentation.razor
@@ -50,6 +50,13 @@
+
+
+ Set the OnClick callback to react when a doughnut segment is selected. The callback receives ChartClickEventArgs with the dataset, item index, label, and raw value; the demo displays the selected item below the chart.
+
+
+
+
@code {
private const string pageUrl = DemoRouteConstants.Demos_DoughnutChart;
private const string pageTitle = "Doughnut Chart";
@@ -57,4 +64,4 @@
private const string metaTitle = "Blazor Doughnut Chart Demo & Examples";
private const string metaDescription = "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.";
private const string imageUrl = DemoImageSrcConstants.DoughnutChart;
-}
\ No newline at end of file
+}
diff --git a/BlazorExpress.ChartJS.Demo.RCL/Pages/Demos/DoughnutChart/DoughnutChart_Demo_03_Click_Event.razor b/BlazorExpress.ChartJS.Demo.RCL/Pages/Demos/DoughnutChart/DoughnutChart_Demo_03_Click_Event.razor
new file mode 100644
index 00000000..ff8c8512
--- /dev/null
+++ b/BlazorExpress.ChartJS.Demo.RCL/Pages/Demos/DoughnutChart/DoughnutChart_Demo_03_Click_Event.razor
@@ -0,0 +1,47 @@
+
+
+@if (selectedChartItem is not null)
+{
+
+ Selected: @selectedChartItem.DatasetLabel (dataset @selectedChartItem.DatasetIndex), @selectedChartItem.Label (index @selectedChartItem.Index), value @selectedChartItem.Value
+
+}
+
+@code {
+ private DoughnutChart doughnutChart = default!;
+ private DoughnutChartOptions doughnutChartOptions = default!;
+ private ChartData chartData = default!;
+ private ChartClickEventArgs? selectedChartItem;
+
+ protected override void OnInitialized()
+ {
+ chartData = new ChartData
+ {
+ Labels = new List { "Direct", "Referral", "Social" },
+ Datasets = new List
+ {
+ new DoughnutChartDataset
+ {
+ Label = "Visitors",
+ Data = new List { 55, 30, 15 },
+ BackgroundColor = new List { "#36A2EB", "#FF6384", "#FFCE56" },
+ },
+ },
+ };
+ doughnutChartOptions = new DoughnutChartOptions { Responsive = true };
+ }
+
+ protected override async Task OnAfterRenderAsync(bool firstRender)
+ {
+ if (firstRender)
+ await doughnutChart.InitializeAsync(chartData, doughnutChartOptions);
+
+ await base.OnAfterRenderAsync(firstRender);
+ }
+
+ private Task HandleClickAsync(ChartClickEventArgs eventArgs)
+ {
+ selectedChartItem = eventArgs;
+ return Task.CompletedTask;
+ }
+}
diff --git a/BlazorExpress.ChartJS.Demo.RCL/Pages/Demos/LineChart/LineChartDocumentation.razor b/BlazorExpress.ChartJS.Demo.RCL/Pages/Demos/LineChart/LineChartDocumentation.razor
index e760ad2d..d0bd58b4 100644
--- a/BlazorExpress.ChartJS.Demo.RCL/Pages/Demos/LineChart/LineChartDocumentation.razor
+++ b/BlazorExpress.ChartJS.Demo.RCL/Pages/Demos/LineChart/LineChartDocumentation.razor
@@ -144,6 +144,13 @@
+
+
+ Set the OnClick callback to react when a line data point is selected. The callback receives ChartClickEventArgs with the dataset, point index, label, and raw value; the demo displays the selected item below the chart.
+
+
+
+
@code {
private const string pageUrl = DemoRouteConstants.Demos_LineChart;
private const string pageTitle = "Line Chart";
diff --git a/BlazorExpress.ChartJS.Demo.RCL/Pages/Demos/LineChart/LineChart_Demo_08_Click_Event.razor b/BlazorExpress.ChartJS.Demo.RCL/Pages/Demos/LineChart/LineChart_Demo_08_Click_Event.razor
new file mode 100644
index 00000000..7c6101c7
--- /dev/null
+++ b/BlazorExpress.ChartJS.Demo.RCL/Pages/Demos/LineChart/LineChart_Demo_08_Click_Event.razor
@@ -0,0 +1,50 @@
+
+
+@if (selectedChartItem is not null)
+{
+
+ Selected: @selectedChartItem.DatasetLabel (dataset @selectedChartItem.DatasetIndex), @selectedChartItem.Label (index @selectedChartItem.Index), value @selectedChartItem.Value
+
+}
+
+@code {
+ private LineChart lineChart = default!;
+ private LineChartOptions lineChartOptions = default!;
+ private ChartData chartData = default!;
+ private ChartClickEventArgs? selectedChartItem;
+
+ protected override void OnInitialized()
+ {
+ chartData = new ChartData
+ {
+ Labels = new List { "Monday", "Tuesday", "Wednesday", "Thursday" },
+ Datasets = new List
+ {
+ new LineChartDataset
+ {
+ Label = "Visitors",
+ Data = new List { 120, 190, 150, 230 },
+ BackgroundColor = "rgba(54, 162, 235, 0.2)",
+ BorderColor = "rgb(54, 162, 235)",
+ PointRadius = new List { 5 },
+ PointHoverRadius = new List { 8 },
+ },
+ },
+ };
+ lineChartOptions = new LineChartOptions { Responsive = true };
+ }
+
+ protected override async Task OnAfterRenderAsync(bool firstRender)
+ {
+ if (firstRender)
+ await lineChart.InitializeAsync(chartData, lineChartOptions);
+
+ await base.OnAfterRenderAsync(firstRender);
+ }
+
+ private Task HandleClickAsync(ChartClickEventArgs eventArgs)
+ {
+ selectedChartItem = eventArgs;
+ return Task.CompletedTask;
+ }
+}
diff --git a/BlazorExpress.ChartJS.Demo.RCL/Pages/Demos/PieChart/PieChartDocumentation.razor b/BlazorExpress.ChartJS.Demo.RCL/Pages/Demos/PieChart/PieChartDocumentation.razor
index fe47d712..fc51bf1a 100644
--- a/BlazorExpress.ChartJS.Demo.RCL/Pages/Demos/PieChart/PieChartDocumentation.razor
+++ b/BlazorExpress.ChartJS.Demo.RCL/Pages/Demos/PieChart/PieChartDocumentation.razor
@@ -70,6 +70,13 @@
+
+
+ Set the OnClick callback to react when a pie slice is selected. The callback receives ChartClickEventArgs with the dataset, item index, label, and raw value; the demo displays the selected item below the chart.
+
+
+
+
@code {
private const string pageUrl = DemoRouteConstants.Demos_PieChart;
private const string pageTitle = "Pie Chart";
diff --git a/BlazorExpress.ChartJS.Demo.RCL/Pages/Demos/PieChart/PieChart_Demo_04_Click_Event.razor b/BlazorExpress.ChartJS.Demo.RCL/Pages/Demos/PieChart/PieChart_Demo_04_Click_Event.razor
new file mode 100644
index 00000000..843abe64
--- /dev/null
+++ b/BlazorExpress.ChartJS.Demo.RCL/Pages/Demos/PieChart/PieChart_Demo_04_Click_Event.razor
@@ -0,0 +1,47 @@
+
+
+@if (selectedChartItem is not null)
+{
+
+ Selected: @selectedChartItem.DatasetLabel (dataset @selectedChartItem.DatasetIndex), @selectedChartItem.Label (index @selectedChartItem.Index), value @selectedChartItem.Value
+
+}
+
+@code {
+ private PieChart pieChart = default!;
+ private PieChartOptions pieChartOptions = default!;
+ private ChartData chartData = default!;
+ private ChartClickEventArgs? selectedChartItem;
+
+ protected override void OnInitialized()
+ {
+ chartData = new ChartData
+ {
+ Labels = new List { "Desktop", "Tablet", "Mobile" },
+ Datasets = new List
+ {
+ new PieChartDataset
+ {
+ Label = "Sessions",
+ Data = new List { 62, 18, 20 },
+ BackgroundColor = new List { "#4BC0C0", "#9966FF", "#FF9F40" },
+ },
+ },
+ };
+ pieChartOptions = new PieChartOptions { Responsive = true };
+ }
+
+ protected override async Task OnAfterRenderAsync(bool firstRender)
+ {
+ if (firstRender)
+ await pieChart.InitializeAsync(chartData, pieChartOptions);
+
+ await base.OnAfterRenderAsync(firstRender);
+ }
+
+ private Task HandleClickAsync(ChartClickEventArgs eventArgs)
+ {
+ selectedChartItem = eventArgs;
+ return Task.CompletedTask;
+ }
+}
diff --git a/BlazorExpress.ChartJS.Demo.RCL/Pages/Demos/PolarAreaChart/PolarAreaChartDocumentation.razor b/BlazorExpress.ChartJS.Demo.RCL/Pages/Demos/PolarAreaChart/PolarAreaChartDocumentation.razor
index b7c24236..22bb743d 100644
--- a/BlazorExpress.ChartJS.Demo.RCL/Pages/Demos/PolarAreaChart/PolarAreaChartDocumentation.razor
+++ b/BlazorExpress.ChartJS.Demo.RCL/Pages/Demos/PolarAreaChart/PolarAreaChartDocumentation.razor
@@ -33,6 +33,13 @@
+
+
+ Set the OnClick callback to react when a polar-area segment is selected. The callback receives ChartClickEventArgs with the dataset, item index, label, and raw value; the demo displays the selected item below the chart.
+
+
+
+
@code {
private const string pageUrl = DemoRouteConstants.Demos_PolarAreaChart;
private const string pageTitle = "PolarArea Chart";
diff --git a/BlazorExpress.ChartJS.Demo.RCL/Pages/Demos/PolarAreaChart/PolarAreaChart_Demo_02_Click_Event.razor b/BlazorExpress.ChartJS.Demo.RCL/Pages/Demos/PolarAreaChart/PolarAreaChart_Demo_02_Click_Event.razor
new file mode 100644
index 00000000..9da1b9f1
--- /dev/null
+++ b/BlazorExpress.ChartJS.Demo.RCL/Pages/Demos/PolarAreaChart/PolarAreaChart_Demo_02_Click_Event.razor
@@ -0,0 +1,53 @@
+
+
+@if (selectedChartItem is not null)
+{
+
+ Selected: @selectedChartItem.DatasetLabel (dataset @selectedChartItem.DatasetIndex), @selectedChartItem.Label (index @selectedChartItem.Index), value @selectedChartItem.Value
+
+}
+
+@code {
+ private PolarAreaChart polarAreaChart = default!;
+ private PolarAreaChartOptions polarAreaChartOptions = default!;
+ private ChartData chartData = default!;
+ private ChartClickEventArgs? selectedChartItem;
+
+ protected override void OnInitialized()
+ {
+ chartData = new ChartData
+ {
+ Labels = new List { "North", "South", "East", "West" },
+ Datasets = new List
+ {
+ new PolarAreaChartDataset
+ {
+ Label = "Sales",
+ Data = new List { 35, 55, 40, 25 },
+ BackgroundColor = new List
+ {
+ "rgba(255, 99, 132, 0.5)",
+ "rgba(54, 162, 235, 0.5)",
+ "rgba(255, 206, 86, 0.5)",
+ "rgba(75, 192, 192, 0.5)",
+ },
+ },
+ },
+ };
+ polarAreaChartOptions = new PolarAreaChartOptions { Responsive = true };
+ }
+
+ protected override async Task OnAfterRenderAsync(bool firstRender)
+ {
+ if (firstRender)
+ await polarAreaChart.InitializeAsync(chartData, polarAreaChartOptions);
+
+ await base.OnAfterRenderAsync(firstRender);
+ }
+
+ private Task HandleClickAsync(ChartClickEventArgs eventArgs)
+ {
+ selectedChartItem = eventArgs;
+ return Task.CompletedTask;
+ }
+}
diff --git a/BlazorExpress.ChartJS.Demo.RCL/Pages/Demos/RadarChart/RadarChartDocumentation.razor b/BlazorExpress.ChartJS.Demo.RCL/Pages/Demos/RadarChart/RadarChartDocumentation.razor
index 8ef6443e..b43a6de2 100644
--- a/BlazorExpress.ChartJS.Demo.RCL/Pages/Demos/RadarChart/RadarChartDocumentation.razor
+++ b/BlazorExpress.ChartJS.Demo.RCL/Pages/Demos/RadarChart/RadarChartDocumentation.razor
@@ -33,6 +33,13 @@
+
+
+ Set the OnClick callback to react when a radar data point is selected. The callback receives ChartClickEventArgs with the dataset, point index, label, and raw value; the demo displays the selected item below the chart.
+
+
+
+
@code {
private const string pageUrl = DemoRouteConstants.Demos_RadarChart;
private const string pageTitle = "Radar Chart";
diff --git a/BlazorExpress.ChartJS.Demo.RCL/Pages/Demos/RadarChart/RadarChart_Demo_02_Click_Event.razor b/BlazorExpress.ChartJS.Demo.RCL/Pages/Demos/RadarChart/RadarChart_Demo_02_Click_Event.razor
new file mode 100644
index 00000000..7f697f74
--- /dev/null
+++ b/BlazorExpress.ChartJS.Demo.RCL/Pages/Demos/RadarChart/RadarChart_Demo_02_Click_Event.razor
@@ -0,0 +1,50 @@
+
+
+@if (selectedChartItem is not null)
+{
+
+ Selected: @selectedChartItem.DatasetLabel (dataset @selectedChartItem.DatasetIndex), @selectedChartItem.Label (index @selectedChartItem.Index), value @selectedChartItem.Value
+
+}
+
+@code {
+ private RadarChart radarChart = default!;
+ private RadarChartOptions radarChartOptions = default!;
+ private ChartData chartData = default!;
+ private ChartClickEventArgs? selectedChartItem;
+
+ protected override void OnInitialized()
+ {
+ chartData = new ChartData
+ {
+ Labels = new List { "Speed", "Reliability", "Comfort", "Safety", "Efficiency" },
+ Datasets = new List
+ {
+ new RadarChartDataset
+ {
+ Label = "Vehicle A",
+ Data = new List { 80, 72, 65, 90, 78 },
+ BackgroundColor = "rgba(153, 102, 255, 0.2)",
+ BorderColor = "rgba(153, 102, 255, 0.8)",
+ BorderWidth = 2,
+ Fill = true,
+ },
+ },
+ };
+ radarChartOptions = new RadarChartOptions { Responsive = true };
+ }
+
+ protected override async Task OnAfterRenderAsync(bool firstRender)
+ {
+ if (firstRender)
+ await radarChart.InitializeAsync(chartData, radarChartOptions);
+
+ await base.OnAfterRenderAsync(firstRender);
+ }
+
+ private Task HandleClickAsync(ChartClickEventArgs eventArgs)
+ {
+ selectedChartItem = eventArgs;
+ return Task.CompletedTask;
+ }
+}
diff --git a/BlazorExpress.ChartJS.Demo.RCL/Pages/Demos/ScatterChart/ScatterChartDocumentation.razor b/BlazorExpress.ChartJS.Demo.RCL/Pages/Demos/ScatterChart/ScatterChartDocumentation.razor
index c1431bdc..98f61ff1 100644
--- a/BlazorExpress.ChartJS.Demo.RCL/Pages/Demos/ScatterChart/ScatterChartDocumentation.razor
+++ b/BlazorExpress.ChartJS.Demo.RCL/Pages/Demos/ScatterChart/ScatterChartDocumentation.razor
@@ -52,6 +52,13 @@
+
+
+ Set the OnClick callback to react when a scatter point is selected. The callback receives ChartClickEventArgs with the dataset, point index, and raw coordinates; the demo displays the selected item below the chart.
+
+
+
+
@code {
private const string pageUrl = DemoRouteConstants.Demos_ScatterChart;
private const string pageTitle = "Scatter Chart";
diff --git a/BlazorExpress.ChartJS.Demo.RCL/Pages/Demos/ScatterChart/ScatterChart_Demo_03_Click_Event.razor b/BlazorExpress.ChartJS.Demo.RCL/Pages/Demos/ScatterChart/ScatterChart_Demo_03_Click_Event.razor
new file mode 100644
index 00000000..e3b65ac6
--- /dev/null
+++ b/BlazorExpress.ChartJS.Demo.RCL/Pages/Demos/ScatterChart/ScatterChart_Demo_03_Click_Event.razor
@@ -0,0 +1,55 @@
+
+
+@if (selectedChartItem is not null)
+{
+
+ Selected: @selectedChartItem.DatasetLabel (dataset @selectedChartItem.DatasetIndex), @(selectedChartItem.Label ?? $"point {selectedChartItem.Index}") (index @selectedChartItem.Index), value @selectedChartItem.Value
+
+}
+
+@code {
+ private ScatterChart scatterChart = default!;
+ private ScatterChartOptions scatterChartOptions = default!;
+ private ChartData chartData = default!;
+ private ChartClickEventArgs? selectedChartItem;
+
+ protected override void OnInitialized()
+ {
+ chartData = new ChartData
+ {
+ Labels = new List { "First", "Second", "Third", "Fourth" },
+ Datasets = new List
+ {
+ new ScatterChartDataset
+ {
+ Label = "Measurements",
+ Data = new List
+ {
+ new(10, 25),
+ new(25, 15),
+ new(35, 40),
+ new(50, 30),
+ },
+ BackgroundColor = "rgba(255, 159, 64, 0.6)",
+ BorderColor = "rgb(255, 159, 64)",
+ BorderWidth = 2,
+ },
+ },
+ };
+ scatterChartOptions = new ScatterChartOptions { Responsive = true };
+ }
+
+ protected override async Task OnAfterRenderAsync(bool firstRender)
+ {
+ if (firstRender)
+ await scatterChart.InitializeAsync(chartData, scatterChartOptions);
+
+ await base.OnAfterRenderAsync(firstRender);
+ }
+
+ private Task HandleClickAsync(ChartClickEventArgs eventArgs)
+ {
+ selectedChartItem = eventArgs;
+ return Task.CompletedTask;
+ }
+}
diff --git a/BlazorExpress.ChartJS/ChartComponents/BarChart.razor.cs b/BlazorExpress.ChartJS/ChartComponents/BarChart.razor.cs
index 13118e35..1951554a 100644
--- a/BlazorExpress.ChartJS/ChartComponents/BarChart.razor.cs
+++ b/BlazorExpress.ChartJS/ChartComponents/BarChart.razor.cs
@@ -177,7 +177,7 @@ public override async Task InitializeAsync(ChartData chartData, IChartOptions ch
{
var datasets = BarLineChartSupport.GetSupportedDatasets(chartData);
var data = new { chartData.Labels, Datasets = datasets };
- await JSRuntime.InvokeVoidAsync(BarChartInterop.Initialize, Id, GetChartType(), data, (BarChartOptions)chartOptions, plugins);
+ await JSRuntime.InvokeVoidAsync(BarChartInterop.Initialize, Id, GetChartType(), data, (BarChartOptions)chartOptions, plugins, DotNetObjectReference);
}
}
diff --git a/BlazorExpress.ChartJS/ChartComponents/BubbleChart.razor.cs b/BlazorExpress.ChartJS/ChartComponents/BubbleChart.razor.cs
index 1547854e..6d3d770c 100644
--- a/BlazorExpress.ChartJS/ChartComponents/BubbleChart.razor.cs
+++ b/BlazorExpress.ChartJS/ChartComponents/BubbleChart.razor.cs
@@ -157,7 +157,7 @@ public override async Task InitializeAsync(ChartData chartData, IChartOptions ch
var datasets = chartData.Datasets.OfType();
var data = new { chartData.Labels, Datasets = datasets };
- await JSRuntime.InvokeVoidAsync(BubbleChartInterop.Initialize, Id, GetChartType(), data, (BubbleChartOptions)chartOptions, plugins);
+ await JSRuntime.InvokeVoidAsync(BubbleChartInterop.Initialize, Id, GetChartType(), data, (BubbleChartOptions)chartOptions, plugins, DotNetObjectReference);
}
///
diff --git a/BlazorExpress.ChartJS/ChartComponents/Core/ChartComponentBase.cs b/BlazorExpress.ChartJS/ChartComponents/Core/ChartComponentBase.cs
index ff37ca5c..b9e6859d 100644
--- a/BlazorExpress.ChartJS/ChartComponents/Core/ChartComponentBase.cs
+++ b/BlazorExpress.ChartJS/ChartComponents/Core/ChartComponentBase.cs
@@ -12,6 +12,8 @@ public abstract class ChartComponentBase : BlazorExpressComponentCore, IDisposab
internal ChartType _chartType;
+ private DotNetObjectReference? dotNetObjectReference;
+
#endregion
#region Methods
@@ -76,10 +78,24 @@ public virtual async Task InitializeAsync(ChartData chartData, IChartOptions cha
if (chartData is not null && chartData.Datasets is not null && chartData.Datasets.Any())
{
var _data = GetChartDataObject(chartData);
- await JSRuntime.InvokeVoidAsync(ChartInterop.Initialize, Id, GetChartType(), _data, chartOptions, plugins);
+ await JSRuntime.InvokeVoidAsync(ChartInterop.Initialize, Id, GetChartType(), _data, chartOptions, plugins, DotNetObjectReference);
}
}
+ ///
+ /// Dispatches a chart-item click to the configured callback.
+ ///
+ /// The selected chart data-item metadata.
+ /// A task that represents the asynchronous callback dispatch operation.
+ [JSInvokable]
+ [AddedVersion("1.2.4")]
+ [Description("Dispatches a chart-item click to the configured callback.")]
+ public async Task HandleClickAsync(ChartClickEventArgs eventArgs)
+ {
+ if (OnClick.HasDelegate)
+ await OnClick.InvokeAsync(eventArgs);
+ }
+
//public async Task Render() { }
//public async Task Reset() { }
@@ -139,6 +155,9 @@ protected string GetChartType() =>
protected string ContainerClassNames => ContainerClass!;
+ protected DotNetObjectReference DotNetObjectReference =>
+ dotNetObjectReference ??= Microsoft.JSInterop.DotNetObjectReference.Create(this);
+
protected string ContainerStyleNames =>
BuildStyleNames(
ContainerStyle,
@@ -241,6 +260,18 @@ private object GetChartDataObject(ChartData chartData)
protected bool IsRenderComplete { get; private set; }
+ ///
+ /// Gets or sets the callback that is invoked when a chart data item is selected.
+ ///
+ /// Default value is .
+ ///
+ ///
+ [AddedVersion("1.2.4")]
+ [DefaultValue(null)]
+ [Description("Gets or sets the callback that is invoked when a chart data item is selected.")]
+ [Parameter]
+ public EventCallback OnClick { get; set; }
+
///
/// Gets or sets chart container width.
/// The default unit of measure is .
@@ -272,6 +303,14 @@ private object GetChartDataObject(ChartData chartData)
#region Other
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing)
+ dotNetObjectReference?.Dispose();
+
+ base.Dispose(disposing);
+ }
+
~ChartComponentBase()
{
Dispose(false);
diff --git a/BlazorExpress.ChartJS/ChartComponents/DoughnutChart.razor.cs b/BlazorExpress.ChartJS/ChartComponents/DoughnutChart.razor.cs
index 1bce4978..573007a1 100644
--- a/BlazorExpress.ChartJS/ChartComponents/DoughnutChart.razor.cs
+++ b/BlazorExpress.ChartJS/ChartComponents/DoughnutChart.razor.cs
@@ -156,7 +156,7 @@ public override async Task InitializeAsync(ChartData chartData, IChartOptions ch
{
var datasets = chartData.Datasets.OfType();
var data = new { chartData.Labels, Datasets = datasets };
- await JSRuntime.InvokeVoidAsync(DoughnutChartInterop.Initialize, Id, GetChartType(), data, (DoughnutChartOptions)chartOptions, plugins);
+ await JSRuntime.InvokeVoidAsync(DoughnutChartInterop.Initialize, Id, GetChartType(), data, (DoughnutChartOptions)chartOptions, plugins, DotNetObjectReference);
}
}
diff --git a/BlazorExpress.ChartJS/ChartComponents/LineChart.razor.cs b/BlazorExpress.ChartJS/ChartComponents/LineChart.razor.cs
index 8c9c7f0d..5ef99166 100644
--- a/BlazorExpress.ChartJS/ChartComponents/LineChart.razor.cs
+++ b/BlazorExpress.ChartJS/ChartComponents/LineChart.razor.cs
@@ -184,7 +184,7 @@ public override async Task InitializeAsync(ChartData chartData, IChartOptions ch
var datasets = BarLineChartSupport.GetSupportedDatasets(chartData);
var data = new { chartData.Labels, Datasets = datasets };
- await JSRuntime.InvokeVoidAsync(LineChartInterop.Initialize, Id, GetChartType(), data, (LineChartOptions)chartOptions, plugins);
+ await JSRuntime.InvokeVoidAsync(LineChartInterop.Initialize, Id, GetChartType(), data, (LineChartOptions)chartOptions, plugins, DotNetObjectReference);
}
///
diff --git a/BlazorExpress.ChartJS/ChartComponents/PieChart.razor.cs b/BlazorExpress.ChartJS/ChartComponents/PieChart.razor.cs
index bf303122..2aa9c019 100644
--- a/BlazorExpress.ChartJS/ChartComponents/PieChart.razor.cs
+++ b/BlazorExpress.ChartJS/ChartComponents/PieChart.razor.cs
@@ -156,7 +156,7 @@ public override async Task InitializeAsync(ChartData chartData, IChartOptions ch
{
var datasets = chartData.Datasets.OfType();
var data = new { chartData.Labels, Datasets = datasets };
- await JSRuntime.InvokeVoidAsync(PieChartInterop.Initialize, Id, GetChartType(), data, (PieChartOptions)chartOptions, plugins);
+ await JSRuntime.InvokeVoidAsync(PieChartInterop.Initialize, Id, GetChartType(), data, (PieChartOptions)chartOptions, plugins, DotNetObjectReference);
}
}
diff --git a/BlazorExpress.ChartJS/ChartComponents/PolarAreaChart.razor.cs b/BlazorExpress.ChartJS/ChartComponents/PolarAreaChart.razor.cs
index e97ae02a..e258b800 100644
--- a/BlazorExpress.ChartJS/ChartComponents/PolarAreaChart.razor.cs
+++ b/BlazorExpress.ChartJS/ChartComponents/PolarAreaChart.razor.cs
@@ -150,7 +150,7 @@ public override async Task InitializeAsync(ChartData chartData, IChartOptions ch
{
var datasets = chartData.Datasets.OfType();
var data = new { chartData.Labels, Datasets = datasets };
- await JSRuntime.InvokeVoidAsync(PolarAreaChartInterop.Initialize, Id, GetChartType(), data, (PolarAreaChartOptions)chartOptions, plugins);
+ await JSRuntime.InvokeVoidAsync(PolarAreaChartInterop.Initialize, Id, GetChartType(), data, (PolarAreaChartOptions)chartOptions, plugins, DotNetObjectReference);
}
}
diff --git a/BlazorExpress.ChartJS/ChartComponents/RadarChart.razor.cs b/BlazorExpress.ChartJS/ChartComponents/RadarChart.razor.cs
index fe27d8da..a92ca63f 100644
--- a/BlazorExpress.ChartJS/ChartComponents/RadarChart.razor.cs
+++ b/BlazorExpress.ChartJS/ChartComponents/RadarChart.razor.cs
@@ -150,7 +150,7 @@ public override async Task InitializeAsync(ChartData chartData, IChartOptions ch
{
var datasets = chartData.Datasets.OfType();
var data = new { chartData.Labels, Datasets = datasets };
- await JSRuntime.InvokeVoidAsync(RadarChartInterop.Initialize, Id, GetChartType(), data, (RadarChartOptions)chartOptions, plugins);
+ await JSRuntime.InvokeVoidAsync(RadarChartInterop.Initialize, Id, GetChartType(), data, (RadarChartOptions)chartOptions, plugins, DotNetObjectReference);
}
}
diff --git a/BlazorExpress.ChartJS/ChartComponents/ScatterChart.razor.cs b/BlazorExpress.ChartJS/ChartComponents/ScatterChart.razor.cs
index 2321dcf1..fb68f974 100644
--- a/BlazorExpress.ChartJS/ChartComponents/ScatterChart.razor.cs
+++ b/BlazorExpress.ChartJS/ChartComponents/ScatterChart.razor.cs
@@ -157,7 +157,7 @@ public override async Task InitializeAsync(ChartData chartData, IChartOptions ch
var datasets = chartData.Datasets.OfType();
var data = new { chartData.Labels, Datasets = datasets };
- await JSRuntime.InvokeVoidAsync(ScatterChartInterop.Initialize, Id, GetChartType(), data, (ScatterChartOptions)chartOptions, plugins);
+ await JSRuntime.InvokeVoidAsync(ScatterChartInterop.Initialize, Id, GetChartType(), data, (ScatterChartOptions)chartOptions, plugins, DotNetObjectReference);
}
///
diff --git a/BlazorExpress.ChartJS/Models/ChartClickEventArgs.cs b/BlazorExpress.ChartJS/Models/ChartClickEventArgs.cs
new file mode 100644
index 00000000..d2f25c0d
--- /dev/null
+++ b/BlazorExpress.ChartJS/Models/ChartClickEventArgs.cs
@@ -0,0 +1,49 @@
+namespace BlazorExpress.ChartJS;
+
+///
+/// Provides information about a selected chart data item.
+///
+public class ChartClickEventArgs
+{
+ #region Properties, Indexers
+
+ ///
+ /// Gets or sets the index of the selected dataset.
+ ///
+ [AddedVersion("1.2.4")]
+ [Description("Gets or sets the index of the selected dataset.")]
+ public int DatasetIndex { get; set; }
+
+ ///
+ /// Gets or sets the label of the selected dataset.
+ ///
+ [AddedVersion("1.2.4")]
+ [DefaultValue(null)]
+ [Description("Gets or sets the label of the selected dataset.")]
+ public string? DatasetLabel { get; set; }
+
+ ///
+ /// Gets or sets the index of the selected data item.
+ ///
+ [AddedVersion("1.2.4")]
+ [Description("Gets or sets the index of the selected data item.")]
+ public int Index { get; set; }
+
+ ///
+ /// Gets or sets the label of the selected data item.
+ ///
+ [AddedVersion("1.2.4")]
+ [DefaultValue(null)]
+ [Description("Gets or sets the label of the selected data item.")]
+ public string? Label { get; set; }
+
+ ///
+ /// Gets or sets the raw value of the selected data item.
+ ///
+ [AddedVersion("1.2.4")]
+ [DefaultValue(null)]
+ [Description("Gets or sets the raw value of the selected data item.")]
+ public JsonElement? Value { get; set; }
+
+ #endregion
+}
diff --git a/BlazorExpress.ChartJS/Usings.cs b/BlazorExpress.ChartJS/Usings.cs
index 7f28513a..55872776 100644
--- a/BlazorExpress.ChartJS/Usings.cs
+++ b/BlazorExpress.ChartJS/Usings.cs
@@ -4,4 +4,5 @@
global using System.ComponentModel;
global using System.Drawing;
global using System.Globalization;
+global using System.Text.Json;
global using System.Text.Json.Serialization;
diff --git a/BlazorExpress.ChartJS/wwwroot/blazorexpress.chartjs.js b/BlazorExpress.ChartJS/wwwroot/blazorexpress.chartjs.js
index c8746fd6..6ba5fdbb 100644
--- a/BlazorExpress.ChartJS/wwwroot/blazorexpress.chartjs.js
+++ b/BlazorExpress.ChartJS/wwwroot/blazorexpress.chartjs.js
@@ -39,6 +39,26 @@ if (!window.blazorexpress.chartjs.scatter) {
}
window.blazorexpress.chartjs = {
+ addClickHandler: (chart, dotNetObjectReference) => {
+ if (!chart || !chart.canvas || !dotNetObjectReference || chart.blazorExpressClickHandler) return;
+
+ chart.blazorExpressClickHandler = true;
+ chart.canvas.addEventListener('click', (event) => {
+ const activeElements = chart.getElementsAtEventForMode(event, 'nearest', { intersect: true }, true);
+ if (!activeElements || activeElements.length === 0) return;
+
+ const activeElement = activeElements[0];
+ const dataset = chart.data.datasets?.[activeElement.datasetIndex];
+
+ dotNetObjectReference.invokeMethodAsync('HandleClickAsync', {
+ datasetIndex: activeElement.datasetIndex,
+ datasetLabel: dataset?.label ?? null,
+ index: activeElement.index,
+ label: chart.data.labels?.[activeElement.index] ?? null,
+ value: dataset?.data?.[activeElement.index] ?? null
+ }).catch(() => { });
+ });
+ },
create: (elementId, type, data, options, plugins) => {
let chartEl = document.getElementById(elementId);
let _plugins = [];
@@ -72,11 +92,14 @@ window.blazorexpress.chartjs = {
return chart;
},
- initialize: (elementId, type, data, options, plugins) => {
+ initialize: (elementId, type, data, options, plugins, dotNetObjectReference) => {
let chart = window.blazorexpress.chartjs.get(elementId);
- if (chart) return;
- else
+ if (!chart) {
window.blazorexpress.chartjs.create(elementId, type, data, options, plugins);
+ chart = window.blazorexpress.chartjs.get(elementId);
+ }
+
+ window.blazorexpress.chartjs.addClickHandler(chart, dotNetObjectReference);
},
resize: (elementId, width, height) => {
let chart = window.blazorexpress.chartjs.get(elementId);
@@ -201,11 +224,14 @@ window.blazorexpress.chartjs.bar = {
return chart;
},
- initialize: (elementId, type, data, options, plugins) => {
+ initialize: (elementId, type, data, options, plugins, dotNetObjectReference) => {
let chart = window.blazorexpress.chartjs.bar.get(elementId);
- if (chart) return;
- else
+ if (!chart) {
window.blazorexpress.chartjs.bar.create(elementId, type, data, options, plugins);
+ chart = window.blazorexpress.chartjs.bar.get(elementId);
+ }
+
+ window.blazorexpress.chartjs.addClickHandler(chart, dotNetObjectReference);
},
resize: (elementId, width, height) => {
let chart = window.blazorexpress.chartjs.bar.get(elementId);
@@ -313,11 +339,14 @@ window.blazorexpress.chartjs.bubble = {
return chart;
},
- initialize: (elementId, type, data, options, plugins) => {
+ initialize: (elementId, type, data, options, plugins, dotNetObjectReference) => {
let chart = window.blazorexpress.chartjs.bubble.get(elementId);
- if (chart) return;
- else
+ if (!chart) {
window.blazorexpress.chartjs.bubble.create(elementId, type, data, options, plugins);
+ chart = window.blazorexpress.chartjs.bubble.get(elementId);
+ }
+
+ window.blazorexpress.chartjs.addClickHandler(chart, dotNetObjectReference);
},
resize: (elementId, width, height) => {
let chart = window.blazorexpress.chartjs.bubble.get(elementId);
@@ -431,11 +460,14 @@ window.blazorexpress.chartjs.doughnut = {
return chart;
},
- initialize: (elementId, type, data, options, plugins) => {
+ initialize: (elementId, type, data, options, plugins, dotNetObjectReference) => {
let chart = window.blazorexpress.chartjs.doughnut.get(elementId);
- if (chart) return;
- else
+ if (!chart) {
window.blazorexpress.chartjs.doughnut.create(elementId, type, data, options, plugins);
+ chart = window.blazorexpress.chartjs.doughnut.get(elementId);
+ }
+
+ window.blazorexpress.chartjs.addClickHandler(chart, dotNetObjectReference);
},
resize: (elementId, width, height) => {
let chart = window.blazorexpress.chartjs.doughnut.get(elementId);
@@ -581,12 +613,14 @@ window.blazorexpress.chartjs.line = {
return chart;
},
- initialize: (elementId, type, data, options, plugins) => {
+ initialize: (elementId, type, data, options, plugins, dotNetObjectReference) => {
let chart = window.blazorexpress.chartjs.line.get(elementId);
- if (chart)
- return;
- else
+ if (!chart) {
window.blazorexpress.chartjs.line.create(elementId, type, data, options, plugins);
+ chart = window.blazorexpress.chartjs.line.get(elementId);
+ }
+
+ window.blazorexpress.chartjs.addClickHandler(chart, dotNetObjectReference);
},
resize: (elementId, width, height) => {
let chart = window.blazorexpress.chartjs.line.get(elementId);
@@ -701,11 +735,14 @@ window.blazorexpress.chartjs.pie = {
return chart;
},
- initialize: (elementId, type, data, options, plugins) => {
+ initialize: (elementId, type, data, options, plugins, dotNetObjectReference) => {
let chart = window.blazorexpress.chartjs.pie.get(elementId);
- if (chart) return;
- else
+ if (!chart) {
window.blazorexpress.chartjs.pie.create(elementId, type, data, options, plugins);
+ chart = window.blazorexpress.chartjs.pie.get(elementId);
+ }
+
+ window.blazorexpress.chartjs.addClickHandler(chart, dotNetObjectReference);
},
resize: (elementId, width, height) => {
let chart = window.blazorexpress.chartjs.pie.get(elementId);
@@ -820,11 +857,14 @@ window.blazorexpress.chartjs.polarArea = {
return chart;
},
- initialize: (elementId, type, data, options, plugins) => {
+ initialize: (elementId, type, data, options, plugins, dotNetObjectReference) => {
let chart = window.blazorexpress.chartjs.polarArea.get(elementId);
- if (chart) return;
- else
+ if (!chart) {
window.blazorexpress.chartjs.polarArea.create(elementId, type, data, options, plugins);
+ chart = window.blazorexpress.chartjs.polarArea.get(elementId);
+ }
+
+ window.blazorexpress.chartjs.addClickHandler(chart, dotNetObjectReference);
},
resize: (elementId, width, height) => {
let chart = window.blazorexpress.chartjs.polarArea.get(elementId);
@@ -938,11 +978,14 @@ window.blazorexpress.chartjs.radar = {
return chart;
},
- initialize: (elementId, type, data, options, plugins) => {
+ initialize: (elementId, type, data, options, plugins, dotNetObjectReference) => {
let chart = window.blazorexpress.chartjs.radar.get(elementId);
- if (chart) return;
- else
+ if (!chart) {
window.blazorexpress.chartjs.radar.create(elementId, type, data, options, plugins);
+ chart = window.blazorexpress.chartjs.radar.get(elementId);
+ }
+
+ window.blazorexpress.chartjs.addClickHandler(chart, dotNetObjectReference);
},
resize: (elementId, width, height) => {
let chart = window.blazorexpress.chartjs.radar.get(elementId);
@@ -1073,11 +1116,14 @@ window.blazorexpress.chartjs.scatter = {
return chart;
},
- initialize: (elementId, type, data, options, plugins) => {
+ initialize: (elementId, type, data, options, plugins, dotNetObjectReference) => {
let chart = window.blazorexpress.chartjs.scatter.get(elementId);
- if (chart) return;
- else
+ if (!chart) {
window.blazorexpress.chartjs.scatter.create(elementId, type, data, options, plugins);
+ chart = window.blazorexpress.chartjs.scatter.get(elementId);
+ }
+
+ window.blazorexpress.chartjs.addClickHandler(chart, dotNetObjectReference);
},
resize: (elementId, width, height) => {
let chart = window.blazorexpress.chartjs.scatter.get(elementId);
@@ -1121,4 +1167,4 @@ window.blazorexpress.chartjs.scatter = {
chart.update();
}
}
-}
\ No newline at end of file
+}