From a77be2dfbadac092288b83e4af1ae60b2d5005dd Mon Sep 17 00:00:00 2001 From: jeremy bayse Date: Sun, 2 Aug 2026 11:04:59 +0200 Subject: [PATCH] Fix intermittent chart rendering on dashboard and flux window.Chart is set by app.js, a deferred module script whose execution isn't ordered relative to Livewire's own script that fires alpine:init. When Livewire won the race, Alpine's x-init called new Chart() before window.Chart existed, silently failing with no console output and leaving the canvas blank. Retry init() until window.Chart is available instead of assuming it's ready. Co-Authored-By: Claude Sonnet 5 --- resources/views/livewire/dashboard/index.blade.php | 7 +++++++ resources/views/livewire/sankey/index.blade.php | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/resources/views/livewire/dashboard/index.blade.php b/resources/views/livewire/dashboard/index.blade.php index f99d409..6c17319 100644 --- a/resources/views/livewire/dashboard/index.blade.php +++ b/resources/views/livewire/dashboard/index.blade.php @@ -157,6 +157,13 @@ Alpine.data('donutChart', (labels, data, palette) => ({ chart: null, init() { + // window.Chart comes from a separately deferred module script + // (app.js) that isn't guaranteed to have run yet when Alpine + // boots, so wait for it instead of racing. + if (typeof window.Chart === 'undefined') { + setTimeout(() => this.init(), 20); + return; + } // Visible stroke between slices so adjacent segments stay // distinguishable even when their fill colors are close (WCAG 1.4.11). const surface = getComputedStyle(document.documentElement).getPropertyValue('--color-surface').trim(); diff --git a/resources/views/livewire/sankey/index.blade.php b/resources/views/livewire/sankey/index.blade.php index ae8fd1b..d195a99 100644 --- a/resources/views/livewire/sankey/index.blade.php +++ b/resources/views/livewire/sankey/index.blade.php @@ -81,6 +81,13 @@ Alpine.data('sankeyChart', (flows) => ({ chart: null, init() { + // window.Chart comes from a separately deferred module script + // (app.js) that isn't guaranteed to have run yet when Alpine + // boots, so wait for it instead of racing. + if (typeof window.Chart === 'undefined') { + setTimeout(() => this.init(), 20); + return; + } const style = getComputedStyle(document.documentElement); const surface = `rgb(${style.getPropertyValue('--color-surface').trim()})`; const text = `rgb(${style.getPropertyValue('--color-text').trim()})`;