Search code examples
laravelhighchartslaravel-livewire

Highchart reload not working but disappearing


I'm using Livewire 3.5 on a personal project, with Highcharts.js. When I first render my component, everything is ok, my chart is correctly displayed.

Then I change my select, and the component is rendered again, with the correct data everywhere. But my Highchart div is emptied and even if I dispatch an event which is catched by my document.addEventListener, the Highchart is not rendering again, even if I copy / paste the exact same code in it...

Here is some commented code, with the simplest Highchart object. This code is in my resources/views/livewire/display.blade.php

On first component render, I can see "On first render : HERE !" in my console. Then I update, my select, the dispatch is well done, the "UPDATE" is displayed in my console... but the div where I had a chart with "TITLE" is now disappeared.

<select class="form-select form-select-lg mb-3" wire:change="change" wire:model="year">
    <option value="2024">Option 1</option>
    <option value="2023">Option 2</option>
    <option value="2022">Option 3</option>
</select>

<figure class="highcharts-figure">
    <div id="hemicycle-reel"></div>
</figure>

@script
<script>

    $(document).ready( function () {
        console.log('On first render : HERE !');
        chart_reel = Highcharts.chart('hemicycle-reel', {
            chart: {
                type: 'item'
            },
            title: {
                text: 'TITLE'
            }
        });

        document.addEventListener('on-change', () => {
            console.log('UPDATE');
            chart_reel = Highcharts.chart('hemicycle-reel', {
                chart: {
                    type: 'item'
                },
                title: {
                    text: 'NEW TITLE'
                }
            });
        });
    });

</script>
@endscript

Here is my component class:

namespace App\Livewire;

class Display extends Component
{
    public $year = '2024';
    public $first_time_render = true;

    public function change()
    {
        // Nothing is done in this method
    }


    public function render()
    {
        // Some process here
        // (..)

        if ($this->is_first_passage == false) {
            $this->dispatch('on-change');
        }

        $this->is_first_passage = false;
        return view('livewire.display');
    }
}

Now, if I try to update my code by using a timeout, instead of document.addEventListener, it's working correctly: the title is changed after 2000ms.

@script
<script>

    $(document).ready( function () {
        console.log('On first render : HERE !');
        chart_reel = Highcharts.chart('hemicycle-reel', {
            chart: {
                type: 'item'
            },
            title: {
                text: 'TITLE'
            }
        });

        setTimeout(function () {
            console.log('UPDATE');
            chart_reel = Highcharts.chart('hemicycle-reel', {
                chart: {
                    type: 'item'
                },
                title: {
                    text: 'NEW TITLE'
                }
            });
        }, 2000);
    });

</script>
@endscript

So this is why I'm asking for help on the Livewire forum :-)

Thanks for your help :-)


Solution

  • You should show the relavant code of the class and the view, and an example of the data is needed too.

    Anyway in this cases the first thing to do is to wrap the tag managed by the javascript library (Highchart in your case) with a <div> with the wire:ignore attribute

    <div wire:ignore>
    
       <div id="hemicycle-reel" ..... > </div>
    
    </div>
    

    This way Livewire won't interfere with that tag

    Edit

    Looking at and testing the new published code I can only confirm my solution: wrap a <div> around the tags handled by Highchart:

    <div wire:ignore>
        <figure class="highcharts-figure">
            <div id="hemicycle-reel"></div>
        </figure>
    </div>
    

    The only addition I made is:

    public $is_first_passage = true;
    public $year = 2024;
    

    because they were missing from the class

    However it is not clear why you need to perform two passages and where/when you think you should set $is_first_passage to true

    Also note that Highcharts has features to vary the chart data without completely redrawing it