Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Livewire Modals Laravel Package

bastinald/laravel-livewire-modals

View on GitHub
Deep Wiki
Context7

Getting Started

Install and wire it up (5 minutes).

composer require bastinald/laravel-livewire-modals

The package is a thin layer: a single Livewire component (usually livewire:modals) that renders a Bootstrap modal shell, listens for an event, and mounts whatever Livewire component you name into the modal body. So installation is two steps, not one:

  1. Drop the modals component into your layout once, near the end of <body> (after Bootstrap's JS):
{{-- resources/views/layouts/app.blade.php --}}
@livewireScripts
<livewire:modals />
  1. From any Livewire component, fire the "show" event with a component alias and optional params:
// app/Http/Livewire/Users/Index.php
$this->emit('showModal', 'users.create');

…where users.create resolves to App\Http\Livewire\Users\Create — a perfectly ordinary Livewire component whose Blade view contains just the modal body content (no modal, modal-dialog, or modal-content wrappers; the package owns those).

Where to look first. Open vendor/bastinald/laravel-livewire-modals/src/ before writing any code. There are only a handful of files, and two things matter: the exact event names (show/hide) and the parameter shape the modals component expects. Everything you do day-to-day is built on those two facts, and the README is terse enough that reading the source is faster than guessing. Also check whether the package ships a publishable Blade view — you will almost certainly want to tweak the modal shell (size="lg", centered, scrollable) eventually.

First use case. The canonical one: a "Create User" button on an index page that opens a form modal, submits, closes, and refreshes the table. Build that end-to-end before touching anything else — it exercises every part of the package (event → mount → validate → close → notify parent) and will surface any Bootstrap/JS wiring problems immediately.

Implementation Patterns

Keep modal components small and single-purpose. The modal component is a normal Livewire component, so it has its own mount(), rules(), render(), and lifecycle hooks. Resist the urge to reuse your index component as a modal. The clean split is: parent owns the list and the "open" button; modal owns the form, validation, and persistence; on success the modal emits an event the parent listens for.

class Create extends Component
{
    public $name, $email;

    public function mount() { $this->reset(['name', 'email']); }

    public function save()
    {
        $this->validate();
        User::create(['name' => $this->name, 'email' => $this->email]);
        $this->emit('hideModal');
        $this->emit('userSaved');
    }
}

One modal component, two modes. For create/edit, pass an optional ID and branch in mount():

$this->emit('showModal', ['users.form', $user->id ?? null]);

public function mount($userId = null)
{
    $this->user = $userId ? User::findOrFail($userId) : new User;
}

Pass scalar IDs, not Eloquent models — Livewire 2 will serialize public model properties, but you get stale data and bloated payloads, and the authorization check in the modal becomes the only real gate anyway.

Refresh the parent on close. Emit a domain event (userSaved, postDeleted) from the modal and $refresh or re-query in the parent's listener. Don't reach into the parent component directly; the event is the seam, and it keeps the modal reusable from multiple pages.

Confirmation dialogs are a good second use. A tiny modals.confirm component with a message property and an onConfirm event name is worth the 30 lines — it removes every confirm() call from your app and matches the rest of the UI.

Close on validation failure is not automatic. $this->validate() throws a ValidationException which Livewire handles in-place; the modal stays open and errors render. That's the behaviour you want, but only works if your modal Blade includes @error('name') blocks — Bootstrap's is-invalid / invalid-feedback classes are the natural fit.

Trigger from JavaScript when needed. Livewire.emit('showModal', 'users.create') works anywhere in your page JS, which is handy for opening a modal from a data table row action rendered outside Livewire.

Testing. The package adds no test surface of its own. Test the modal component in isolation (Livewire::test(Users\Create::class)->set('name', ...)->call('save')) and assert the parent reacts to the emitted events (->assertEmitted('userSaved')). Skip testing the modal chrome.

Gotchas and Tips

Forgetting <livewire:modals /> fails silently. The emit goes nowhere, no error, no modal. This is the single most common "the package is broken" report. If nothing happens, check the layout first, then the browser console for Livewire is not defined (scripts order), then the event name spelling.

Livewire 2 and Bootstrap 4 are the target. The package predates Livewire 3's dispatch() API, so emit() is the dialect throughout. If you're on Livewire 3 you'll be fighting the package; the event bridge still works in compatibility mode but you're better off with a Livewire-3-native modal package. Same story for Bootstrap 4: it needs jQuery and Popper loaded before @livewireScripts; Bootstrap 5 does not, and mixing the two is a classic source of "modal appears but is invisible" (that's the .fade + missing jQuery transition).

Dynamic component state leaks between opens. Livewire caches components by key. If you open the edit modal for user #1, close, then open it for user #2, you can get stale properties. Fix with a wire:key that includes the modal target and params, or a hard $this->reset() in mount() — preferably both.

Nested modals and backdrops. Bootstrap only supports one backdrop cleanly. If you spawn a confirmation modal from inside an edit modal, the second backdrop and z-index will fight the first. Either close the parent first, or set data-backdrop="static" on the inner one and manage the body class (modal-open) yourself. Expect to spend an hour here; budget for it.

Params come from the client. The event payload is browser-controlled. Never let a modal mount() do User::find($id) and assume the current user can edit it — re-authorize inside the modal, every time. This is the package's one real security consideration and it's easy to miss because the trigger looks like server-side code.

Extension points are limited by design. There's no config file to speak of; customization means publishing and editing the modal Blade view, or rolling your own shell that emits the same events. That's fine — the component is ~30 lines — but don't expect a plugin architecture.

Debugging the event bus. Livewire.on('showModal', console.log) in the browser tells you instantly whether the problem is on the emit side (no log → component didn't fire or wasn't hydrated) or the render side (log fires, no modal → modals component missing or view broken). Two minutes saved every time.

Maintenance risk. 68 stars, low activity, no Livewire 3 path. Treat it as a small piece of vendored infrastructure rather than a dependency you'll upgrade forever — and keep your own modal components free of package-specific calls (just events) so swapping it out later is a find-and-replace on two event names rather than a rewrite.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle