切换Program后图表消失求助(控制台可获取数据)
问题描述
默认仪表板中选择第一个Program时图表显示正常;切换至其他Program后,图表消失。控制台能成功获取对应数据,但图表无法渲染。
相关代码
Livewire组件类代码
public $program_id = ""; public $activites = []; public $data = []; public $budget = []; public $documentCount = 0; public function render() { if ($this->program_id == "") { $program = Program::all()->first(); } else { $program = Program::find($this->program_id); } if ($program) { $activites = $program->activities->groupBy('statut_id')->map->count(); $statuts = Statut::whereIn('id', $activites->keys())->pluck('nom', 'id'); $budgetProgramme = $program->budget; $this->documentCount = $program->documents->count(); $budgetActivites = $program->activities->sum('budget'); $this->budget = [ 'budget_programme' => $budgetProgramme, 'budget_activite' => $budgetActivites, ]; $this->data = [ 'cree' => $statuts->search('crée') !== false ? $activites->get($statuts->search('crée'), 0) : 0, 'cours' => $statuts->search('en cours') !== false ? $activites->get($statuts->search('en cours'), 0) : 0, 'finalisee' => $statuts->search('finalisée') !== false ? $activites->get($statuts->search('finalisée'), 0) : 0, 'retard' => $statuts->search('retard') !== false ? $activites->get($statuts->search('retard'), 0) : 0, ]; $this->dispatchBrowserEvent('updateChart', $this->data); $this->dispatchBrowserEvent('updateBudgetChart', $this->budget); } return view('livewire.programs.dashboard', [ "programs" => Program::all(), ]); }
Blade视图代码
<div> <div class="card"> <div class="row"> <div class="col-md-12"> <h4 class="text-center"><span class="badge badge-secondary">Documents ressources total :{{$documentCount}} </span></h4> <hr> <div class="input-group input-group"> <span class="input-group-addon">Programme</span> <select wire:model="program_id" id="program" class="form-control" required> <option value="">Veuillez sélectionner le programme</option> @foreach ($programs as $program) <option value="{{ $program->id }}"> {{ $program->nom }} </option> @endforeach </select> </div> <div class="row"> <div class="col-md-6"> <div class="chart-container" style="position: relative; height:50vh; width:100vw"> <canvas id="houseChart"></canvas> </div> </div> <div class="col-md-6"> <div class="chart-container" style="position: relative; height:40vh; width:80vw"> <canvas id="budgetHistogramme"></canvas> </div> </div> </div> </div> </div> </div> <script src="https://cdn.jsdelivr.net/npm/chart.js"></script> <script> var houseChartCtx = document.getElementById('houseChart').getContext('2d'); var houseChartData = { labels: ['Crée', 'En cours', 'Finalisé', 'En retard'], datasets: [{ data: [ {{ $data['cree'] }}, {{ $data['cours'] }}, {{ $data['finalisee'] }}, {{ $data['retard'] }}, ], backgroundColor: ['#3498DB', '#F39C12', '#00cc00', '#d9534f'] }] }; var myPieChart = new Chart(houseChartCtx, { type: 'pie', data: houseChartData }); window.addEventListener('updateChart', data => { console.log(data); myPieChart.data.datasets[0].data = data; myPieChart.update(); console.log("apres MAJ"); }); // section budget var budgetChartCtx = document.getElementById('budgetHistogramme').getContext('2d'); var budgetChartData = { labels: ['Budget programme', 'Budget activités'], datasets: [{ data: [ {{ $budget['budget_programme'] }}, {{ $budget['budget_activite'] }}, ], backgroundColor: ['#3498DB', '#F39C12'] }] }; var budgetChart = new Chart(budgetChartCtx, { type: 'bar', data: budgetChartData }); window.addEventListener('updateBudgetChart', data => { console.log(data); budgetChart.data = data; budgetChart.update(); console.log("budget apres MAJ"); }); </script> </div>
解决方案
问题出在前端事件监听的图表数据更新逻辑上,控制台能拿到数据但格式不符合Chart.js的要求:
饼图(houseChart)更新错误
后端dispatch的updateChart事件传递的是关联数组({cree: x, cours: y, ...}),但Chart.js的饼图data需要的是和labels顺序匹配的数组值。修改事件监听代码:window.addEventListener('updateChart', event => { const data = event.detail; myPieChart.data.datasets[0].data = [ data.cree, data.cours, data.finalisee, data.retard ]; myPieChart.update(); });预算柱状图(budgetHistogramme)更新错误
直接把后端传递的关联数组赋值给budgetChart.data会覆盖掉Chart.js需要的labels和datasets结构,只需要更新datasets里的data数组:window.addEventListener('updateBudgetChart', event => { const data = event.detail; budgetChart.data.datasets[0].data = [ data.budget_programme, data.budget_activite ]; budgetChart.update(); });额外优化:避免重复渲染脚本
Livewire每次更新都会重新渲染视图里的script,导致重复创建Chart实例和绑定事件。可以把脚本放到@push或者单独的JS文件中,或者在创建Chart前先销毁旧实例:// 饼图部分 if (window.myPieChart) { window.myPieChart.destroy(); } window.myPieChart = new Chart(houseChartCtx, { type: 'pie', data: houseChartData }); // 预算图部分 if (window.budgetChart) { window.budgetChart.destroy(); } window.budgetChart = new Chart(budgetChartCtx, { type: 'bar', data: budgetChartData });
内容的提问来源于stack exchange,提问作者SAWADOGO SIDIKI
相关产品推荐
相关产品推荐

