apexcharts / Blazor-ApexCharts

A blazor wrapper for ApexCharts.js
https://apexcharts.github.io/Blazor-ApexCharts
MIT License
788 stars 91 forks source link

ArgumentNullException with JSMarkerClick #487

Open razblack opened 1 month ago

razblack commented 1 month ago

I have a handler for "OnMarkerClick" on the ApexChart component that calls an Action:

private void MarkerClick(SelectedData<TrendData> data)
   {
      if (MarkerClicked != null)
      {
          MarkerClicked.Invoke(true);
      }
   }

The action is super simple for the componet with the chart, and is:

[Parameter] public Action<bool>? MarkerClicked { get; set; }

The parameter has a handler for the parent using the componet, which creates some markup, and applies the HTML to a variable that is reference in a simple div:

//in the handler method of the parent

markerHTML.Append($"<div class=\"row\"><strong>Marker ID:</strong><br/>");
markerInfo = new MarkupString(markerHTML.ToString());
StateHasChanged();

inside the razor file

//this is as easy as it gets
<div>@markerInfo</div>

Without the call to StateHasChanged, the HTML in the div does not get updated... no exceptions occur. To force a render of the div, I call StateHasChanged... the first "OnMarkerClick" no issue... all subsequent clicks throw the exception below...

I've tried converting things to async/await and using InvokeAsync(StateHasChanged)... no luck, same problem.

detailed exception:

Uncaught (in promise) Error: System.ArgumentNullException: Value cannot be null. (Parameter 'source') at System.Linq.ThrowHelper.ThrowArgumentNullException(ExceptionArgument argument) at System.Linq.Enumerable.ElementAt[TSource](IEnumerable1 source, Int32 index) at ApexCharts.Internal.JSHandler1.JSMarkerClick(JSDataPointSelection selectedDataPoints) at InvokeStub_JSHandler1.JSMarkerClick(Object, Span1) at System.Reflection.MethodBaseInvoker.InvokeWithOneArg(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) --- End of stack trace from previous location --- at Microsoft.JSInterop.Infrastructure.DotNetDispatcher.InvokeSynchronously(JSRuntime jsRuntime, DotNetInvocationInfo& callInfo, IDotNetObjectReference objectReference, String argsJson) at Microsoft.JSInterop.Infrastructure.DotNetDispatcher.BeginInvokeDotNet(JSRuntime jsRuntime, DotNetInvocationInfo invocationInfo, String argsJson) at y.endInvokeDotNetFromJS (https://localhost/_framework/blazor.server.js:1:3502) at Xt._invokeClientMethod (https://localhost/_framework/blazor.server.js:1:61001) at Xt._processIncomingData (https://localhost/_framework/blazor.server.js:1:58476) at Xt.connection.onreceive (https://localhost/_framework/blazor.server.js:1:52117) at s.onmessage (https://localhost/_framework/blazor.server.js:1:80262)

razblack commented 1 month ago

just a note, I have a somewhat workaround to the exception issue...

I added a handler to a Popup component, that had the HTML that required the StateHasChanged to show the dynamic properties being sent via the OnMarkerClick. (fyi, this is a Radzen component "PopUp").

The handler is defined like:

<Popup @ref=markerPopup class=@popclass style=@popstyle  Close=OnPopupClose>
    <div>@dtNow</div>
    <div class="markerpopup-card">
        <div>@markerInfo</div>
    </div>
</Popup>

The OnPopupClose callback makes a call on the graph reference, then calls StateHasChanged:

private void OnPopupClose()
{
      GraphREF?.ReRenderGraph();
      StateHasChanged();
}

I'm at a loss as to why; however, the exceptions are no longer thrown and I can switch between void and async/await handlers with no issue... for whatever reason, trying to call StateHasChanged is breaking the Chart capability or handle to the callback method assigned to OnMarkerClick.

./shrug