使用Livewire3分页后Flowbite模态框无法正常工作
Livewire 3分页后Flowbite模态框无法触发的解决方案
问题原因
Livewire通过AJAX更新分页内容时,新渲染的按钮元素没有被Flowbite的模态脚本初始化——Flowbite默认只在页面首次加载(DOMContentLoaded)时扫描带有data-modal-toggle等属性的元素并绑定事件,分页后的新元素不会被自动处理。
修复方案
方案1:利用Livewire更新事件重新初始化Flowbite模态
在组件视图的脚本部分,监听Livewire的livewire:update事件,每次DOM更新后重新调用Flowbite的模态初始化方法:
document.addEventListener('livewire:update', function() { // 重新初始化所有Flowbite模态组件 if (typeof window.Flowbite !== 'undefined') { window.Flowbite.initModals(); } });
方案2:改用Livewire响应式逻辑控制模态(推荐)
完全基于Livewire的响应式状态管理模态显示,避免DOM事件绑定问题:
- Livewire组件类添加状态和方法:
namespace App\Livewire; use Livewire\Component; use App\Models\User; class UserTable extends Component { public $selectedUserId = null; public $users; public function mount() { $this->users = User::paginate(10); } public function openModal($userId) { $this->selectedUserId = $userId; } public function closeModal() { $this->selectedUserId = null; } public function render() { return view('livewire.user-table', [ 'users' => $this->users ]); } }
- 修改视图文件:
<div> <div class="overflow-x-auto sm:rounded-lg p-2"> <table class="w-full text-sm text-left text-gray-500 dark:text-gray-400"> <thead class="text-xs text-gray-50 uppercase bg-gray-700 dark:bg-gray-700 dark:text-gray-400"> <tr> <th scope="col" class="px-3 py-1">Id</th> <th scope="col" class="px-3 py-1">Name</th> <th scope="col" class="px-6 py-3">Email</th> <th scope="col" class="px-6 py-3">Created At</th> <th scope="col" class="px-6 py-3">Action</th> </tr> </thead> <tbody> @foreach ($users as $item) <tr class="bg-gray-300 border-b dark:bg-gray-800 dark:border-gray-700"> <th scope="row" class="px-6 py-4 font-medium text-gray-900 whitespace-nowrap dark:text-white"> {{ $item->id }} </th> <td class="px-6 py-4">{{ $item->name }}</td> <td class="px-6 py-4">{{ $item->email }}</td> <td class="px-6 py-4">{{ $item->created_at }}</td> <td class="px-6 py-4"> <button wire:click="openModal({{ $item->id }})" class="block text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800" type="button"> Toggle modal </button> </td> </tr> @endforeach </tbody> </table> {{ $users->links() }} @if ($selectedUserId) @php $user = User::find($selectedUserId); @endphp <div id="popup-modal-{{ $user->id }}" tabindex="-1" class="fixed overflow-y-auto overflow-x-hidden top-0 right-0 left-0 z-50 justify-center items-center w-full md:inset-0 h-[calc(100%-1rem)] max-h-full" wire:click.outside="closeModal"> <div class="relative p-4 w-full max-w-md max-h-full"> <div class="relative bg-white rounded-lg shadow dark:bg-gray-700"> <button type="button" wire:click="closeModal" class="absolute top-3 end-2.5 text-gray-400 bg-transparent hover:bg-gray-200 hover:text-gray-900 rounded-lg text-sm w-8 h-8 ms-auto inline-flex justify-center items-center dark:hover:bg-gray-600 dark:hover:text-white"> <svg class="w-3 h-3" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 14 14"> <path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m1 1 6 6m0 0 6 6M7 7l6-6M7 7l-6 6"/> </svg> <span class="sr-only">Close modal</span> </button> <div class="p-4 md:p-5 text-center"> <svg class="mx-auto mb-4 text-gray-400 w-12 h-12 dark:text-gray-200" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 20 20"> <path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 11V6m0 8h.01M19 10a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z"/> </svg> <h3 class="mb-5 text-lg font-normal text-gray-500 dark:text-gray-400">Are you sure you want to delete this product? - {{ $user->id }}</h3> <button wire:click="closeModal" type="button" class="text-white bg-red-600 hover:bg-red-800 focus:ring-4 focus:outline-none focus:ring-red-300 dark:focus:ring-red-800 font-medium rounded-lg text-sm inline-flex items-center px-5 py-2.5 text-center me-2"> Yes, I'm sure </button> <button wire:click="closeModal" type="button" class="text-gray-500 bg-white hover:bg-gray-100 focus:ring-4 focus:outline-none focus:ring-gray-200 rounded-lg border border-gray-200 text-sm font-medium px-5 py-2.5 hover:text-gray-900 focus:z-10 dark:bg-gray-700 dark:text-gray-300 dark:border-gray-500 dark:hover:text-white dark:hover:bg-gray-600 dark:focus:ring-gray-600"> No, cancel </button> </div> </div> </div> </div> @endif </div> </div>
方案3:手动绑定事件到新元素
如果不想依赖Flowbite的自动初始化,手动封装模态切换逻辑,并在Livewire更新后重新绑定:
// 封装模态切换函数 function toggleModal(event) { const targetId = event.currentTarget.getAttribute('data-modal-target'); const modal = document.getElementById(targetId); if (modal) { modal.classList.toggle('hidden'); // 处理遮罩层 const backdrop = document.querySelector('.fixed.inset-0.bg-gray-900.bg-opacity-50.z-40'); if (!modal.classList.contains('hidden')) { const newBackdrop = document.createElement('div'); newBackdrop.className = 'fixed inset-0 bg-gray-900 bg-opacity-50 z-40'; document.body.appendChild(newBackdrop); newBackdrop.addEventListener('click', () => { modal.classList.add('hidden'); newBackdrop.remove(); }); } else { backdrop?.remove(); } } } // 初始化按钮事件 function initModalButtons() { document.querySelectorAll('[data-modal-toggle]').forEach(button => { button.removeEventListener('click', toggleModal); button.addEventListener('click', toggleModal); }); } // 页面加载和Livewire更新后执行初始化 document.addEventListener('DOMContentLoaded', initModalButtons); document.addEventListener('livewire:update', initModalButtons);
内容的提问来源于stack exchange,提问作者Adnarim
相关产品推荐
相关产品推荐

