You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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事件绑定问题:

  1. 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
        ]);
    }
}
  1. 修改视图文件:
<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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 20:44:58