Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

valentin_vranic's avatar

Livewire 3 + AlpineJS reusable modal

It seems I can't find a proper solution for rendering modal with those two technologies. What I want to achieve is a reusable modal (bootstrap 5), to load Eloquent model to it and generate a form for insert/update.

I've tried with this tutorial: https://www.youtube.com/watch?v=ZQJhabcophk But I ran into issue that even if I reached the render method, it doesn't load the livewire component into it.

0 likes
1 reply
LaryAI's avatar
Level 58

To create a reusable modal with Livewire and Alpine.js, you can follow these steps:

  1. Create a Livewire component for your modal.
  2. Use Alpine.js for handling the display of the modal.
  3. Pass the Eloquent model or its identifier to the Livewire component when you want to open the modal.

Here's a step-by-step guide:

Step 1: Create a Livewire Component

First, create a Livewire component that will be responsible for rendering the modal and handling the form submission.

php artisan make:livewire EditModelModal

Step 2: Define the Component's View

In your Livewire component's view (edit-model-modal.blade.php), you can define the modal structure using Bootstrap 5. Use wire:model to bind your form inputs to the Livewire component's properties.

<!-- edit-model-modal.blade.php -->
<div x-data="{ open: @entangle('isOpen').defer }" @keydown.escape.window="open = false">
    <div x-show="open" class="modal" tabindex="-1" style="display: none;" x-ref="modal" x-on:close.stop="open = false">
        <div class="modal-dialog">
            <div class="modal-content">
                <div class="modal-header">
                    <h5 class="modal-title">Edit Model</h5>
                    <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close" x-on:click="open = false"></button>
                </div>
                <form wire:submit.prevent="save">
                    <div class="modal-body">
                        <!-- Form fields -->
                        <div class="mb-3">
                            <label for="exampleFormControlInput1" class="form-label">Field Name</label>
                            <input type="text" class="form-control" id="exampleFormControlInput1" wire:model="modelName">
                        </div>
                        <!-- Add more fields as needed -->
                    </div>
                    <div class="modal-footer">
                        <button type="button" class="btn btn-secondary" data-bs-dismiss="modal" x-on:click="open = false">Close</button>
                        <button type="submit" class="btn btn-primary">Save changes</button>
                    </div>
                </form>
            </div>
        </div>
    </div>
    <div x-show="open" class="modal-backdrop fade show" x-on:click="open = false"></div>
</div>

Step 3: Define the Component's Class

In your Livewire component class (EditModelModal.php), handle the loading of the model and the save method.

// EditModelModal.php
use Livewire\Component;

class EditModelModal extends Component
{
    public $isOpen = false;
    public $modelId;
    public $modelName; // Replace with actual property names

    protected $listeners = ['openModal' => 'open'];

    public function open($modelId)
    {
        $this->modelId = $modelId;
        $this->loadModel();
        $this->isOpen = true;
    }

    public function loadModel()
    {
        $model = YourEloquentModel::find($this->modelId);
        $this->modelName = $model->name; // Replace with actual field names
        // Load other model properties as needed
    }

    public function save()
    {
        // Validation and save logic
        $model = YourEloquentModel::find($this->modelId);
        $model->name = $this->modelName; // Replace with actual field names
        // Update other model properties as needed
        $model->save();

        $this->isOpen = false;
        $this->emit('modelUpdated'); // Emit an event if needed
    }

    public function render()
    {
        return view('livewire.edit-model-modal');
    }
}

Step 4: Use the Component

To use the modal, include the Livewire component in your main view and use Alpine.js to trigger the modal.

<!-- In your main view -->
<div>
    <!-- Trigger button -->
    <button @click="$dispatch('open-modal', { id: 1 })">Edit Model</button>

    <!-- Livewire modal component -->
    @livewire('edit-model-modal')
</div>

<script>
    document.addEventListener('alpine:init', () => {
        Alpine.data('modalTrigger', () => ({
            init() {
                this.$root.addEventListener('open-modal', event => {
                    this.$wire.openModal(event.detail.id);
                });
            }
        }));

        Alpine.start();
    });
</script>

Make sure to replace YourEloquentModel with the actual model you are using and adjust the property names and form fields accordingly.

This setup allows you to have a reusable modal component that can be triggered from anywhere in your application. The openModal method in the Livewire component is responsible for loading the model data and opening the modal, while the save method handles the form submission.

Please or to participate in this conversation.