mariusmuntean / ChartJs.Blazor

Brings Chart.js charts to Blazor
https://www.iheartblazor.com/
MIT License
676 stars 151 forks source link

If hidden, charts never come back #163

Open Gabriel-RABHI opened 3 years ago

Gabriel-RABHI commented 3 years ago

Hi,

The chart is well displayed the first time. If not displayed and displayed again, an empty small html canvas remain on the page and the chart will never be visible again. To reproduce this bug i have modified the "Basic.cs" sample to add a toogle button :

@page "/charts/line/basic"
@using ChartJs.Blazor.LineChart
@layout SampleLayout

<button @onclick="SwitchShow">Toogle</button>
@if (_show)
{
<Chart Config="_config" @ref="_chart"></Chart>
}

<button @onclick="RandomizeData">Randomize Data</button>
<button @onclick="AddDataset">Add Dataset</button>
<button @onclick="RemoveDataset">Remove Dataset</button>
<button @onclick="AddData">Add Data</button>
<button @onclick="RemoveData">Remove Data</button>

@code {
    private bool _show = true;
    public void SwitchShow()
    {
        _show = !_show;
        _chart.
    }

I've seen that another dev have had the problem, but it seems the bug is here again !

Thank you !

larschristensen20 commented 3 years ago

Did you try calling StateHasChanged() in your

public void SwitchShow()
    {
        _show = !_show;
        _chart.
    }

method after _show = !_show;

It tells Blazor to re-render the UI.

Gabriel-RABHI commented 3 years ago

Something like that do not work :

public void SwitchShow() { _show = !_show; _chart.Update(); StateHasChanged(); }

But I've found a hack : rebuilding the entire Config to force the component to call the JS Interop again. By specifying a new Config object, the component seems to track a change that induce a new JS Interop call and then the charts is rebuilded client side.

Add a toogle button in any sample and you'll see the problem. It is really disturbing the first time, but it seems to be a classic drawback of JS based components in blazor...

(a guess that's why real native blazor components are better in terme of efficiency, productivity and reliability)

larschristensen20 commented 3 years ago

Yeah I just tried in my own project, and there is definitely something amiss here, my chart does not re-render just like you confirmed. A possible work-around might be to create a targeted JS interop to the method needed to show the chart (if you can find it, that is).

Sorry I can't help much more than that :D

Joelius300 commented 3 years ago

Hey @Gabriel-RABHI, thanks for the issue :)

You've observed correctly, I can easily reproduce the problem. The issue is that blazor will completely remove the canvas from the dom when it's hidden (AFAIK).

I think we would have to detect when the chart gets removed from the dom and re-initialize the chart when that happens (potentially without playing animations since it isn't the first render).

Does anyone have an idea how to do that?