diff --git a/src/Blazor-ApexCharts/Internal/Converters/NullToDefaultIntConverter.cs b/src/Blazor-ApexCharts/Internal/Converters/NullToDefaultIntConverter.cs new file mode 100644 index 00000000..cff8ebc8 --- /dev/null +++ b/src/Blazor-ApexCharts/Internal/Converters/NullToDefaultIntConverter.cs @@ -0,0 +1,39 @@ +using System; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace ApexCharts.Internal +{ + internal class NullToDefaultIntConverter : JsonConverter + { + public override int Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + if (reader.TokenType == JsonTokenType.Null) + { + return -1; // Default value for null + } + + if (reader.TokenType == JsonTokenType.Number && reader.TryGetInt32(out int value)) + { + return value; // Handle numeric values + } + + if (reader.TokenType == JsonTokenType.String) + { + string stringValue = reader.GetString(); + if (int.TryParse(stringValue, out int parsedValue)) + { + return parsedValue; // Handle string values that can be parsed as int + } + return -1; // Default value for invalid strings + } + + throw new JsonException($"Cannot convert {reader.GetString() ?? "null"} to int."); + } + + public override void Write(Utf8JsonWriter writer, int value, JsonSerializerOptions options) + { + writer.WriteNumberValue(value); + } + } +} diff --git a/src/Blazor-ApexCharts/Internal/JSHandler.cs b/src/Blazor-ApexCharts/Internal/JSHandler.cs index eb8ccfeb..e478f52e 100644 --- a/src/Blazor-ApexCharts/Internal/JSHandler.cs +++ b/src/Blazor-ApexCharts/Internal/JSHandler.cs @@ -1,12 +1,8 @@ -using Microsoft.AspNetCore.Components; -using Microsoft.Extensions.Options; -using Microsoft.JSInterop; +using Microsoft.JSInterop; using System; using System.Collections.Generic; using System.Linq; -using System.Reflection; using System.Text.Json; -using System.Threading.Tasks; namespace ApexCharts.Internal { @@ -19,6 +15,16 @@ internal sealed class JSHandler : IDisposable where TItem : class private readonly ApexChart ChartReference; internal readonly DotNetObjectReference> ObjectReference; + private readonly JsonSerializerOptions DeserializeOptions = new JsonSerializerOptions + { + PropertyNameCaseInsensitive = true, // Handle case mismatches + DefaultIgnoreCondition = System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull, // Ignore null when serializing + NumberHandling = System.Text.Json.Serialization.JsonNumberHandling.AllowReadingFromString, // Allow read numbers from strings + AllowTrailingCommas = true, // Handle malformed JSON gracefully + ReadCommentHandling = JsonCommentHandling.Skip, // Handle potential comments in JSON + Converters = { new NullToDefaultIntConverter() } // Add the custom converter + }; + internal JSHandler(ApexChart chartReference) { ObjectReference = DotNetObjectReference.Create(this); @@ -41,8 +47,10 @@ public void Dispose() [JSInvokable] public string JSGetFormattedYAxisValue(JsonElement value) { - if (value.ValueKind == JsonValueKind.Null) { return ""; } - if (ChartReference.FormatYAxisLabel == null) { return value.ToString(); } + if (value.ValueKind == JsonValueKind.Null) + { return ""; } + if (ChartReference.FormatYAxisLabel == null) + { return value.ToString(); } if (value.ValueKind == JsonValueKind.Number && value.TryGetDecimal(out var decimalValue)) { @@ -62,8 +70,10 @@ public string JSGetFormattedYAxisValue(JsonElement value) [JSInvokable] public string JSGetFormattedXAxisValue(JsonElement value) { - if (value.ValueKind == JsonValueKind.Null) { return ""; } - if (ChartReference.FormatXAxisLabel == null) { return value.ToString(); } + if (value.ValueKind == JsonValueKind.Null) + { return ""; } + if (ChartReference.FormatXAxisLabel == null) + { return value.ToString(); } if (value.ValueKind == JsonValueKind.Number && value.TryGetDecimal(out var decimalValue)) { @@ -76,13 +86,14 @@ public string JSGetFormattedXAxisValue(JsonElement value) /// /// Callback from JavaScript on zoom /// - /// Details from JavaScript + /// Details from JavaScript /// /// Will execute /// [JSInvokable] - public void JSZoomed(JSZoomed jSZoomed) + public void JSZoomed(JsonElement value) { + JSZoomed jSZoomed = value.Deserialize(DeserializeOptions); if (ChartReference.OnZoomed.HasDelegate) { ChartReference.OnZoomed.InvokeAsync(new ZoomedData @@ -97,13 +108,14 @@ public void JSZoomed(JSZoomed jSZoomed) /// /// Callback from JavaScript on selection updated /// - /// Details from JavaScript + /// Details from JavaScript /// /// Will execute /// [JSInvokable] - public void JSBrushScrolled(JSSelection jsSelection) + public void JSBrushScrolled(JsonElement value) { + JSSelection jsSelection = value.Deserialize(DeserializeOptions); if (ChartReference.OnBrushScrolled.HasDelegate) { ChartReference.OnBrushScrolled.InvokeAsync(new SelectionData @@ -118,13 +130,14 @@ public void JSBrushScrolled(JSSelection jsSelection) /// /// Callback from JavaScript on selection updated /// - /// Details from JavaScript + /// Details from JavaScript /// /// Will execute /// [JSInvokable] - public void JSSelected(JSSelection jsSelection) + public void JSSelected(JsonElement value) { + JSSelection jsSelection = value.Deserialize(DeserializeOptions); if (ChartReference.OnSelection.HasDelegate) { ChartReference.OnSelection.InvokeAsync(new SelectionData @@ -139,13 +152,14 @@ public void JSSelected(JSSelection jsSelection) /// /// Callback from JavaScript on a legend item clicked /// - /// Details from JavaScript + /// Details from JavaScript /// /// Will execute /// [JSInvokable] - public void JSLegendClicked(JSLegendClicked jsLegendClicked) + public void JSLegendClicked(JsonElement value) { + JSLegendClicked jsLegendClicked = value.Deserialize(DeserializeOptions); Series series = null; IDataPoint point = null; if (ChartReference.IsNoAxisChart) @@ -179,13 +193,14 @@ public void JSLegendClicked(JSLegendClicked jsLegendClicked) /// /// Callback from JavaScript on an X-axis label clicked /// - /// Details from JavaScript + /// Details from JavaScript /// /// Will execute /// [JSInvokable] - public void JSXAxisLabelClick(JSXAxisLabelClick jsXAxisLabelClick) + public void JSXAxisLabelClick(JsonElement value) { + JSXAxisLabelClick jsXAxisLabelClick = value.Deserialize(DeserializeOptions); if (ChartReference.OnXAxisLabelClick.HasDelegate) { var data = new XAxisLabelClicked() @@ -211,13 +226,14 @@ public void JSXAxisLabelClick(JSXAxisLabelClick jsXAxisLabelClick) /// /// Callback from JavaScript on marker clicked /// - /// Details from JavaScript + /// Details from JavaScript /// /// Will execute /// [JSInvokable] - public void JSMarkerClick(JSDataPointSelection selectedDataPoints) + public void JSMarkerClick(JsonElement value) { + JSDataPointSelection selectedDataPoints = value.Deserialize(DeserializeOptions); if (ChartReference.OnMarkerClick.HasDelegate) { var series = ChartReference.Options.Series.ElementAt(selectedDataPoints.SeriesIndex); @@ -240,13 +256,14 @@ public void JSMarkerClick(JSDataPointSelection selectedDataPoints) /// /// Callback from JavaScript on data point selected /// - /// Details from JavaScript + /// Details from JavaScript /// /// Will execute /// [JSInvokable] - public void JSDataPointSelected(JSDataPointSelection selectedDataPoints) + public void JSDataPointSelected(JsonElement value) { + JSDataPointSelection selectedDataPoints = value.Deserialize(DeserializeOptions); if (ChartReference.OnDataPointSelection.HasDelegate) { var series = ChartReference.Options.Series.ElementAt(selectedDataPoints.SeriesIndex); @@ -269,20 +286,18 @@ public void JSDataPointSelected(JSDataPointSelection selectedDataPoints) /// /// Callback from JavaScript on data point enter /// - /// Details from JavaScript + /// Details from JavaScript /// /// Will execute /// [JSInvokable] - public void JSDataPointEnter(JSDataPointSelection selectedDataPoints) + public void JSDataPointEnter(JsonElement value) { + JSDataPointSelection selectedDataPoints = value.Deserialize(DeserializeOptions); if (ChartReference.OnDataPointEnter.HasDelegate) { - var hoverData = GetHoverData(selectedDataPoints); ChartReference.OnDataPointEnter.InvokeAsync(hoverData); - - } } @@ -291,7 +306,7 @@ private HoverData GetHoverData(JSDataPointSelection selectedDataPoints) var series = ChartReference.Options.Series.ElementAt(selectedDataPoints.SeriesIndex); var dataPoint = series.Data.ElementAt(selectedDataPoints.DataPointIndex); - return new HoverData + return new HoverData { Chart = ChartReference, Series = series, @@ -302,8 +317,9 @@ private HoverData GetHoverData(JSDataPointSelection selectedDataPoints) } [JSInvokable] - public void RazorTooltip(JSDataPointSelection selectedDataPoints) + public void RazorTooltip(JsonElement value) { + JSDataPointSelection selectedDataPoints = value.Deserialize(DeserializeOptions); if (ChartReference.ApexPointTooltip != null) { var hoverData = GetHoverData(selectedDataPoints); @@ -312,16 +328,17 @@ public void RazorTooltip(JSDataPointSelection selectedDataPoints) } - /// - /// Callback from JavaScript on data point leave - /// - /// Details from JavaScript - /// - /// Will execute - /// - [JSInvokable] - public void JSDataPointLeave(JSDataPointSelection selectedDataPoints) + /// + /// Callback from JavaScript on data point leave + /// + /// Details from JavaScript + /// + /// Will execute + /// + [JSInvokable] + public void JSDataPointLeave(JsonElement value) { + JSDataPointSelection selectedDataPoints = value.Deserialize(DeserializeOptions); if (ChartReference.OnDataPointLeave.HasDelegate) { var series = ChartReference.Options.Series.ElementAt(selectedDataPoints.SeriesIndex); @@ -412,8 +429,10 @@ public void JSUpdated() /// Will execute /// [JSInvokable] - public void JSMouseMove(JSDataPointSelection selectedDataPoints) + public void JSMouseMove(JsonElement value) { + var selectedDataPoints = value.Deserialize(DeserializeOptions); + var series = selectedDataPoints.SeriesIndex >= 0 ? ChartReference.Options.Series.ElementAt(selectedDataPoints.SeriesIndex) : null; @@ -451,8 +470,9 @@ public void JSMouseLeave() /// Will execute /// [JSInvokable] - public void JSClick(JSDataPointSelection selectedDataPoints) + public void JSClick(JsonElement value) { + var selectedDataPoints = value.Deserialize(DeserializeOptions); var series = selectedDataPoints.SeriesIndex >= 0 ? ChartReference.Options.Series.ElementAt(selectedDataPoints.SeriesIndex) : null; @@ -478,8 +498,9 @@ public void JSClick(JSDataPointSelection selectedDataPoints) /// Will execute /// [JSInvokable] - public SelectionXAxis JSBeforeZoom(JSSelection jsSelection) + public SelectionXAxis JSBeforeZoom(JsonElement value) { + JSSelection jsSelection = value.Deserialize(DeserializeOptions); return ChartReference.OnBeforeZoom.Invoke(jsSelection.XAxis); } @@ -498,13 +519,14 @@ public SelectionXAxis JSBeforeResetZoom() /// /// Callback from JavaScript on scrolled /// - /// Details from JavaScript + /// Details from JavaScript /// /// Will execute /// [JSInvokable] - public void JSScrolled(JSSelection jsSelection) + public void JSScrolled(JsonElement value) { + JSSelection jsSelection = value.Deserialize(DeserializeOptions); var selectionData = new SelectionData { Chart = ChartReference, @@ -517,10 +539,11 @@ public void JSScrolled(JSSelection jsSelection) /// /// Callback from JavaScript on Annotaion Label Event (Click, MouseLeave, MouseEnter) /// - /// Details from JavaScript + /// Details from JavaScript [JSInvokable] - public void JSAnnotationLabelEvent(JSAnnotationEvent jsAnnotationEvent) + public void JSAnnotationLabelEvent(JsonElement value) { + JSAnnotationEvent jsAnnotationEvent = value.Deserialize(DeserializeOptions); var eventData = new AnnotationEvent { Chart = ChartReference, @@ -550,10 +573,11 @@ public void JSAnnotationLabelEvent(JSAnnotationEvent jsAnnotationEvent) /// /// Callback from JavaScript on Annotaion Label Event (Click, MouseLeave, MouseEnter) /// - /// Details from JavaScript + /// Details from JavaScript [JSInvokable] - public void JSAnnotationPointEvent(JSAnnotationEvent jsAnnotationEvent) + public void JSAnnotationPointEvent(JsonElement value) { + JSAnnotationEvent jsAnnotationEvent = value.Deserialize(DeserializeOptions); var eventData = new AnnotationEvent { Chart = ChartReference,