Install the package:
composer require devsrv/livewire-modal
Include the base modal component in your layout (once globally):
<x-livewiremodal-base />
Ensure this is placed after @livewireStyles and before @livewireScripts in your <body>.
Trigger a modal from a Livewire component:
<button wire:click="$emit('livewire-modal:open', 'modal-component-name')">
Open Modal
</button>
Define your modal component (e.g., ModalComponent.php):
public function render()
{
return view('livewire.modal-component');
}
<!-- resources/views/livewire/modal-component.blade.php -->
<div class="modal-content">
<!-- Your modal content here -->
</div>
Use the built-in alert system for instant feedback:
<button wire:click="$emit('livewire-modal:alert', 'Success!', 'success')">
Show Success Alert
</button>
Supports types: info, warning, success, danger.
<button wire:click="$emit('livewire-modal:open', 'user-edit-modal', { userId: 123 })">
Edit User
</button>
Pass data via the 3rd argument (as JSON).
<button x-on:click="$wire.emit('livewire-modal:open', 'user-edit-modal', { userId: 123 })">
Edit User
</button>
document.querySelector('#open-modal').addEventListener('click', () => {
window.Livewire.emit('livewire-modal:open', 'user-edit-modal');
});
Required: Extend devsrv\LivewireModal\Modal or use $this->modal = true; in your Livewire class.
Example:
public $modal = true;
public $userId;
public function mount($userId)
{
$this->userId = $userId;
}
Dynamic Content:
<div class="modal-header">Edit User #{{ $userId }}</div>
<div class="modal-body">
<!-- Dynamic form here -->
</div>
Listen for modal lifecycle events in your Livewire component:
protected $listeners = [
'modalOpened' => 'onModalOpened',
'modalClosed' => 'onModalClosed',
];
public function onModalOpened()
{
$this->emit('alert', 'Modal opened!', 'info');
}
public function onModalClosed()
{
$this->reset(['formData']);
}
Override default styles by publishing the package assets:
php artisan vendor:publish --provider="devsrv\LivewireModal\LivewireModalServiceProvider" --tag=public
Then extend the CSS in public/css/livewire-modal.css.
Use unique modal names to stack modals:
<button wire:click="$emit('livewire-modal:open', 'modal-level-1')">
Open Level 1
</button>
<!-- Inside modal-level-1 -->
<button wire:click="$emit('livewire-modal:open', 'modal-level-2')">
Open Level 2
</button>
Missing Base Component:
<x-livewiremodal-base /> is included once in your layout.Bootstrap 5 vs. 4:
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
Alpine.js Conflicts:
x-ignore for dynamic content:
<div x-data="{ open: false }" x-ignore>
<!-- Dynamic content -->
</div>
Modal Not Closing:
$this->modal = true; in Livewire class or unhandled exceptions.modalClosed listeners are properly defined.Check Emitted Events: Use browser dev tools to verify events are firing:
window.addEventListener('livewire:initialized', () => {
window.Livewire.on('livewire-modal:open', (name, data) => {
console.log('Modal opened:', name, data);
});
});
Inspect Modal Stack: The package uses a stack system. Log the stack to debug nesting:
protected $listeners = [
'modalStackUpdated' => 'logModalStack',
];
public function logModalStack($stack)
{
\Log::info('Current modal stack:', $stack);
}
Force Modal Close: Manually trigger close via JavaScript for testing:
window.Livewire.emit('livewire-modal:close');
Custom Modal Templates: Override the base modal template by publishing the view:
php artisan vendor:publish --provider="devsrv\LivewireModal\LivewireModalServiceProvider" --tag=views
Then modify resources/views/vendor/livewire-modal/base.blade.php.
Add Animation: Extend the modal class to include animations:
// In your Livewire component
public function mount()
{
$this->modalOptions = [
'animation' => true,
];
}
Global Modal Config:
Set default options in config/livewire-modal.php (published via):
php artisan vendor:publish --provider="devsrv\LivewireModal\LivewireModalServiceProvider" --tag=config
Example config:
'default' => [
'backdrop' => 'static',
'keyboard' => true,
'focus' => true,
],
Server-Side Validation: Combine with Livewire validation for seamless UX:
public function save()
{
$this->validate([
'name' => 'required',
]);
// Save logic
$this->emit('livewire-modal:close');
}
How can I help you explore Laravel packages today?