javascriptphpchart.jslaravel-livewire

Display Chart.js chart(s) depending on Livewire form submission


I am trying to display one or more charts using Chart.js and Laravel Livewire. My issue is that the chart isn't displayed, even if the chart object receive data (when I console.log(chart) I can see the correct data)

I currently don't bother to get actual form data, as I can't even display a chart with dummy data (which was working fine before I tried to introduce Livewire).

Here is some code:

filter-graphs.blade.php (filter view)

<div>
    <form wire:submit="onGraphsChange" class="text-xl w-3/4 mx-auto">
        <div class="flex items-center justify-center">
            <div class="mx-4 flex-1 justify-center">
                <x-input-label for="graphs" value="Graphs à afficher" />
                <select id="graphs" name="graphs" multiple="multiple" class="mt-1 block w-full py-2 bg-gray-200 text-gray-800 rounded focus:border-[#F73F3A] focus:ring-[#F73F3A]">
                    <option class="py-1 bg-gray-200 text-gray-800" value="4">dummy 1</option>
                    <option class="py-1 bg-gray-200 text-gray-800" value="2">dummy 2</option>
                </select>
            </div>
            <div class="mx-4 flex-1 justify-center text-center">
                <button type="submit" class="px-4 py-2 border-2 border-gray-800 text-gray-800 rounded hover:text-gray-200 hover:bg-gray-800 hover:cursor-pointer">Afficher les graphs</button>
            </div>
        </div>
    </form>
</div>

FilterGraphs.php (filter component)

namespace App\Livewire;

use Livewire\Component;

class FilterGraphs extends Component
{
    public $selectedGraphs = null;

    public function onGraphsChange()
    {
        $this->dispatch('graphs-selected', $this->selectedGraphs);
    }

    public function render()
    {
        return view('livewire.filter-graphs');
    }
}

display-graphs.blade.php (charts display view)

<div class="flex">
    <div class="flex-1 shadow-sm rounded-lg bg-white m-4 p-4">
        <canvas id="test-graph"></canvas>
    </div>
</div>

<script>
    document.addEventListener('livewire:init', () => {
        Livewire.on('updateGraphs', (data) => {
            if(Chart.getChart("test-graph"))
                Chart.getChart("test-graph").destroy();

            var ctx = document.getElementById('test-graph').getContext("2d");
            var config = {
                type: 'line',
                data: {
                    labels: data[0]['labels'],
                    datasets: data[0]['datasets']
                },
                options: {
                    scales: {
                        x: {
                           ticks: {
                                display: false
                            },
                            grid: {
                                display: false
                            }
                        }
                    },
                    plugins: {
                        title: {
                            display: true,
                            text: '',
                        }
                    },
                    animation: false
                }
            };

            // myChart.config.options.plugins.title.text = data['title'];
            var myChart = new Chart(ctx, config);
        });
    });
</script>

DisplayGraphs.php (charts display component)

namespace App\Livewire;

use Livewire\Component;

use App\Models\History;

class DisplayGraphs extends Component
{
    public array $datasets = [];
    public array $labels = [];
    public $graphs;

    protected $listeners = [
        'graphs-selected' => 'graphsSelected',
    ];

    public function graphsSelected($server_service_ids)
    {
        //Get the dummy data

        $labels = $dates; // Contains an array of 85 dates as strings

        $datasets = [
            [
                'label' => 'Temps de réponse (ms)',
                'backgroundColor' => 'rgba(247, 63, 58, 0.3)',
                'borderColor' => 'rgb(247, 63, 58)',
                'lineTension' => 0.5,
                'pointRadius' => 2,
                'fill' => true,
                'data' => $response_times, // Contains an array of 85 int
            ],
            [
                'label' => 'Niveau d\'alerte (ms)',
                'backgroundColor' => 'rgba(255, 87, 34, 0.3)',
                'borderColor' => 'rgb(255, 87, 35)',
                'pointRadius' => 0,
                'data' => $alert, // Contains an array of 85 int
            ],
        ];

        $this->dispatch('updateGraphs', [
            'datasets' => $datasets,
            'labels' => $labels,
        ]);
    }

    public function mount()
    {
        $this->labels = [];
        $this->datasets = [];
    }

    public function render()
    {
        return view('livewire.display-graphs');
    }
}

And the view within which I show all that

<x-app-layout>
    <x-slot name="header">
        <h2 class="font-semibold text-xl text-gray-800 dark:text-gray-200 leading-tight">
            Title
        </h2>
    </x-slot>

    <!--Tabs navigation-->
    @include('partials.subnavigation-tabs')

    <livewire:filter-graphs />
    <livewire:display-graphs />
</x-app-layout>

What am I missing here to get the charts to display? Thanks in advance


Solution

  • Ok, nevermind I found the solution.
    The issue was that the canvas is loaded on the page's first load (but with a height of 0), so when I loaded the charts with its configuration, the canvas size did not change and the chart was actually displayed in the same height of 0.

    I added maintainAspectRatio: false in the chart options in order for the canvas to adapt its size to the new chart size.

    Thanks for your help anyway!