You will have to override the app.blade.php
file if you want to add Turbolinks
to the Filament Admin panel.
Steps
hotwire/turbo
filament-turbo.js
webpack.mix.js
base.blade.php
npm install --save-dev @hotwired/turbo
(The paths are based on my application, you don't have to keep this file structure ;)
resources/filament/filament-turbo.js
import '../js/libs/turbo';
resources/js/libs/turbo.js
import * as Turbo from '@hotwired/turbo'; //start Livewire turbolinks, source https://github.com/livewire/turbolinks/blob/master/src/index.js v0.1.4//removes the need for a cdn link in app.blade.phpif (typeof window.Livewire === 'undefined') { throw 'Livewire Turbolinks Plugin: window.Livewire is undefined. Make sure @livewireScripts is placed above this script include'} let firstTime = true; function wireTurboAfterFirstVisit () { // We only want this handler to run AFTER the first load. if (firstTime) { firstTime = false return } window.Livewire.restart() window.Alpine && window.Alpine.flushAndStopDeferringMutations && window.Alpine.flushAndStopDeferringMutations()} function wireTurboBeforeCache() { document.querySelectorAll('[wire\\:id]').forEach(function(el) { const component = el.__livewire; const dataObject = { fingerprint: component.fingerprint, serverMemo: component.serverMemo, effects: component.effects, }; el.setAttribute('wire:initial-data', JSON.stringify(dataObject)); }); window.Alpine && window.Alpine.deferMutations && window.Alpine.deferMutations()} document.addEventListener("turbo:load", wireTurboAfterFirstVisit)document.addEventListener("turbo:before-cache", wireTurboBeforeCache); document.addEventListener("turbolinks:load", wireTurboAfterFirstVisit)document.addEventListener("turbolinks:before-cache", wireTurboBeforeCache); Livewire.hook('beforePushState', (state) => { if (! state.turbolinks) state.turbolinks = {}}) Livewire.hook('beforeReplaceState', (state) => { if (! state.turbolinks) state.turbolinks = {}})//end Livewire turbolinks //start turbo-laravel, source https://github.com/tonysm/turbo-laravel/blob/main/stubs/resources/js/libs/alpine.js v1.1.0document.addEventListener('turbo:before-render', () => { let permanents = document.querySelectorAll('[data-turbo-permanent]'); let undos = Array.from(permanents).map(el => { el._x_ignore = true; return () => { delete el._x_ignore; }; }); document.addEventListener('turbo:render', function handler() { while(undos.length) undos.shift()(); document.removeEventListener('turbo:render', handler); });});//end turbo-laravel export default Turbo;
webpack.mix.js
mix.js('resources/filament/filament-turbo.js', 'public/js').extract(['@hotwired/turbo'], 'js/vendor-turbo.js');
Publish Filament views. Keep only resources/views/vendor/filament/components/layouts/base.blade.php
, it is not a recommended to keep files that you do not intend to override.
php artisan vendor:publish --tag=filament-views
You need to move the Filament scripts to the head
tag and defer
them.
@props([ 'title' => null,])<!DOCTYPE html><html lang="{{ str_replace('_', '-', app()->getLocale()) }}" dir="{{ __('filament::layout.direction') ?? 'ltr' }}" class="filament antialiased bg-gray-100 js-focus-visible"><head> {{ \Filament\Facades\Filament::renderHook('head.start') }} <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="csrf-token" content="{{ csrf_token() }}"> @foreach (\Filament\Facades\Filament::getMeta() as $tag) {{ $tag }} @endforeach @if ($favicon = config('filament.favicon')) <link rel="icon" href="{{ $favicon }}"> @endif <title>{{ $title ? "{$title} - " : null }} {{ config('filament.brand') }}</title> <style> [x-cloak=""], [x-cloak="x-cloak"], [x-cloak="1"] { display: none !important; } @media (max-width: 1023px) { [x-cloak="-lg"] { display: none !important; } } @media (min-width: 1024px) { [x-cloak="lg"] { display: none !important; } } </style> @livewireStyles @if (filled($fontsUrl = config('filament.google_fonts'))) <link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link href="{{ $fontsUrl }}" rel="stylesheet" /> @endif @foreach (\Filament\Facades\Filament::getStyles() as $name => $path) @if (Str::of($path)->startsWith(['http://', 'https://'])) <link rel="stylesheet" href="{{ $path }}" /> @else <link rel="stylesheet" href="{{ route('filament.asset', [ 'file' => "{$name}.css", ]) }}" /> @endif @endforeach <link rel="stylesheet" href="{{ \Filament\Facades\Filament::getThemeUrl() }}" /> @if (config('filament.dark_mode')) <script> const theme = localStorage.getItem('theme') if ((theme === 'dark') || (! theme && window.matchMedia('(prefers-color-scheme: dark)').matches)) { document.documentElement.classList.add('dark') } </script> @endif @livewireScripts <script src="{{ mix('js/manifest.js') }}" defer></script> <script src="{{ mix('js/vendor-turbo.js') }}" defer></script> <script src="{{ mix('js/filament-turbo.js') }}" defer></script> <script> window.filamentData = @json(\Filament\Facades\Filament::getScriptData()); </script> @foreach (\Filament\Facades\Filament::getBeforeCoreScripts() as $name => $path) @if (Str::of($path)->startsWith(['http://', 'https://'])) <script src="{{ $path }}" defer></script> @else <script src="{{ route('filament.asset', [ 'file' => "{$name}.js", ]) }}" defer></script> @endif @endforeach @stack('beforeCoreScripts') <script src="{{ route('filament.asset', [ 'id' => Filament\get_asset_id('app.js'), 'file' => 'app.js', ]) }}" defer></script> @foreach (\Filament\Facades\Filament::getScripts() as $name => $path) @if (Str::of($path)->startsWith(['http://', 'https://'])) <script src="{{ $path }}" defer></script> @else <script src="{{ route('filament.asset', [ 'file' => "{$name}.js", ]) }}" defer></script> @endif @endforeach @stack('scripts') {{ \Filament\Facades\Filament::renderHook('head.end') }}</head> <body @class([ 'bg-gray-100 text-gray-900 filament-body', 'dark:text-gray-100 dark:bg-gray-900' => config('filament.dark_mode'), ])>{{ \Filament\Facades\Filament::renderHook('body.start') }} {{ $slot }} {{ \Filament\Facades\Filament::renderHook('body.end') }}</body></html>
No comments yet…