Installation:
composer require wire-elements/modal
Publish assets (if needed):
npm install && npm run dev
Basic Usage: Register the modal in your Livewire component:
use WireElements\Modal\Modal;
public function mount()
{
$this->modal = new Modal();
}
Add the modal directive to your Blade view:
@livewireScripts
@modalScripts
First Modal: Trigger a modal from a button:
<button wire:click="$dispatch('openModal', {component: 'user.create'})">
Create User
</button>
Define the modal component (e.g., UserCreateModal):
<livewire:user.create wire:key="user-create-modal" />
examples/ folder in the repo for ready-to-use templates.$dispatch/$on for modal interactions (Livewire v3 syntax).<button wire:click="$dispatch('openModal', {
component: 'confirmation-dialog',
props: { message: 'Are you sure?', callback: 'deleteUser' }
})">
Delete User
</button>
// In ConfirmationDialog component
public function deleteUser()
{
$this->emit('closeModal');
// Call parent method (e.g., $this->wire('parent')->deleteUser())
}
Modal Lifecycle:
$dispatch('openModal', {component: '...', props: {...}})$emit('closeModal') or $emit('closeModal', {keepAlive: true})$on('closeModal', callback) in parent components.Dynamic Props:
Pass data dynamically via props:
<button wire:click="$dispatch('openModal', {
component: 'user.edit',
props: { userId: 1, title: 'Edit Profile' }
})">
Edit
</button>
Nested Modals:
Use wire:key to avoid duplication:
<livewire:user.edit wire:key="'edit-user-'.$userId" />
Livewire Components:
wire:model, wire:click, etc.<form wire:submit.prevent="save">
<input wire:model="name">
<button type="submit">Save</button>
</form>
Authentication:
Protect modal content with Livewire’s authorize:
public function rules()
{
return ['name' => 'required|min:3'];
}
public function authorize()
{
return auth()->check();
}
Styling: Use Tailwind/Alpine.js for dynamic classes:
<div x-data="{ open: false }" @open-modal.window="open = true">
<div x-show="open" class="fixed inset-0 bg-black/50">
<!-- Modal content -->
</div>
</div>
Reusable Modals: Create a base modal component:
<!-- resources/views/components/modal.blade.php -->
<div x-data="{ open: false }" @open-modal.window="open = true">
{{ $slot }}
</div>
Modal Stacking:
Use keepAlive to stack modals:
<button wire:click="$dispatch('openModal', {
component: 'modal.a',
keepAlive: true
})">
Open Modal A
</button>
Backdrop Closure: Close modals by clicking outside:
<div @click="$dispatch('closeModal')" class="fixed inset-0"></div>
Modal Events: Listen to modal events in parent components:
public function mount()
{
$this->listen('closeModal', function () {
$this->resetForm();
});
}
Livewire v3 Migration:
$emit → $dispatch (v3) for opening modals.
<!-- v2 -->
<button wire:click="$emit('openModal', 'users')">Show</button>
<!-- v3 -->
<button wire:click="$dispatch('openModal', {component: 'users'})">Show</button>
AppServiceProvider:
Livewire::component('user.create', UserCreateModal::class);
Duplicate Modals:
Always use wire:key to avoid Livewire’s "duplicate ID" errors:
<livewire:user.edit wire:key="'edit-'.$userId" />
State Persistence:
Modals reset state on close unless keepAlive: true is set. Use $persist for critical data:
public $persist = ['userId'];
Alpine.js Conflicts: Ensure Alpine.js directives don’t interfere with Livewire’s event system. Prefix Alpine events:
<div x-data @alpine-open.window="...">
Check Events: Use browser dev tools to verify events are dispatched:
window.addEventListener('openModal', (e) => console.log(e.detail));
Livewire Logs: Enable Livewire debugging:
LIVEWIRE_LOG_LEVEL=debug
Component Isolation: Test modals in isolation by creating a dedicated Livewire component for debugging.
Default Backdrop:
Disable backdrop by passing backdrop: false:
$dispatch('openModal', { component: 'modal', backdrop: false })
Custom Animations: Override default animations via CSS:
.modal-enter-active, .modal-leave-active {
transition: opacity 0.3s;
}
.modal-enter-from, .modal-leave-to {
opacity: 0;
}
Modal Size: Use Tailwind classes or custom CSS for sizing:
<div class="max-w-md w-full">
<!-- Modal content -->
</div>
Custom Modal Components: Extend the base modal logic:
class CustomModal extends Modal
{
public function customize()
{
$this->backdrop = true;
$this->escape = false; // For raw HTML
}
}
Global Modal Events: Listen to all modal events in a service provider:
Livewire::listen('openModal', function ($event) {
Log::info('Modal opened:', $event);
});
Modal Middleware: Add middleware to modals (e.g., auth, validation):
public function mount()
{
$this->middleware([CheckPermission::class]);
}
Theming: Override default styles via CSS variables or a theme provider:
:root {
--modal-bg: #2d3748;
--modal-text: #ffffff;
}
How can I help you explore Laravel packages today?