Installation
composer require linuxstreet/wire-content-modal
Publish Config (Optional)
php artisan vendor:publish --provider="Linuxstreet\WireContentModal\WireContentModalServiceProvider"
First Use Case: Basic Modal Trigger
@livewire('your-component', key('modal-trigger'))
<button wire:click="$dispatch('open-modal', { component: 'your-component', key: 'modal-trigger' })">
Open Modal
</button>
key attribute ensures the modal targets the correct Livewire component instance.Default Modal Blade
Locate the published Blade template at:
resources/views/vendor/wire-content-modal/modal.blade.php
@livewire('dynamic-component', key('dynamic-key'))
<button wire:click="$dispatch('open-modal', {
component: 'dynamic-component',
key: 'dynamic-key',
size: 'lg',
title: 'Custom Title'
})">
Open Dynamic
</button>
size (e.g., sm, md, lg, xl) and title parameters for consistency.$dispatch('open-modal', {
view: 'path.to.view',
data: { key: 'value' } // Optional data to pass to the view
});
wire:ignore on the modal container to prevent Livewire from re-rendering it:
<div wire:ignore>
@include('path.to.view', ['data' => $data])
</div>
// app/Http/Livewire/BaseModal.php
public function mount($key) {
$this->key = $key;
}
Extend this in your components and reuse the same modal trigger logic.<!-- Inside modal component -->
<form wire:submit.prevent="submitForm">
@csrf
<input wire:model="name">
<button type="submit">Save</button>
</form>
public function submitForm() {
$this->validate([...]);
// Save logic
$this->reset(['name']); // Reset only form fields
}
// Global listener (e.g., in a Livewire component)
this.$wire.on('modal-opened', (component) => {
console.log('Opened:', component);
});
open-modal (trigger)modal-opened (after render)modal-closed (after close)Key Collisions
key values can cause modals to target the wrong component.user-{{ $user->id }}-edit-modal).Livewire State Persistence
mount() or updated():
public function mount() {
$this->resetExcept(['persistent_data']);
}
Blade View Data Binding
open-modal isn’t automatically available.wire:ignore and manually pass data:
<div wire:ignore>
@include('view.name', ['data' => $this->data])
</div>
Styling Conflicts
<x-wire-content-modal::modal class="custom-modal-classes">
Check Dispatch Events
window.addEventListener('open-modal', (e) => {
console.log('Modal event:', e.detail);
});
Inspect Livewire Keys
key attributes match between triggers and components:
// Debug in component
dd($this->key); // Should match the dispatched key
Clear Cached Views
php artisan view:clear
Custom Modal Templates
php artisan vendor:publish --tag=wire-content-modal-views
Add Animation
<div x-data="{ open: false }" x-show="open" @open-modal.window="open = true">
<!-- Modal content -->
</div>
Server-Side Logic
WireContentModal facade to trigger modals from server-side code:
use Linuxstreet\WireContentModal\Facades\WireContentModal;
WireContentModal::open('component.name', ['key' => 'unique-key']);
Accessibility
<div role="dialog" aria-modal="true" aria-labelledby="modal-title">
How can I help you explore Laravel packages today?