We will do a simple modal for editing a record for the third mini-project. We will use the same Product
model as in the previous example.
First, let's start by creating a Livewire component and showing a list of products.
php artisan make:livewire EditModal
app/Livewire/EditModal.php:
use App\Models\Product;use Illuminate\Contracts\View\View; class EditModal extends Component{ public function render(): View { return view('livewire.edit-modal', [ 'products' => Product::all(), ]); }}
resouces/views/livewire/edit-modal.blade.php:
<div class="min-w-full align-middle"> <table class="min-w-full border divide-y divide-gray-200"> <thead> <tr> <th class="bg-gray-50 px-6 py-3 text-left"> <span class="text-xs font-medium uppercase leading-4 tracking-wider text-gray-500">Name</span> </th> <th class="bg-gray-50 px-6 py-3 text-left"> <span class="text-xs font-medium uppercase leading-4 tracking-wider text-gray-500">Price</span> </th> <th class="bg-gray-50 px-6 py-3 text-left"> </th> </tr> </thead> <tbody class="bg-white divide-y divide-gray-200 divide-solid"> @forelse($products as $product) <tr class="bg-white"> <td class="px-6 py-4 text-sm leading-5 text-gray-900 whitespace-no-wrap"> {{ $product->name }} </td> <td class="px-6 py-4 text-sm leading-5 text-gray-900 whitespace-no-wrap"> {{ $product->price }} </td> <td class="px-6 py-4 text-sm leading-5 text-gray-900 whitespace-no-wrap"> <a !href="#" class="mt-4 rounded-md bg-gray-800 px-4 py-2 text-xs font-semibold uppercase tracking-widest text-white hover:bg-gray-700"> Edit </a> </td> </tr> @empty <tr> <td class="px-6 py-2 text-sm leading-5 text-gray-900 whitespace-no-wrap" colspan="3">No products found.</td> </tr> @endforelse </tbody> </table></div>
To show and hide a modal, we need a boolean public property. Also, we need properties for binding the form to the product values.
app/Livewire/EditModal.php:
use Livewire\Features\SupportLockedProperties\Locked; class EditModal extends Component{ #[Locked] public int $id; public string $name = ''; public string $price = ''; public bool $showModal = false; // ...}
The id
property is locked, so no one could modify it.
Next, we need a method to show the modal when clicking the edit button. We must also find the product by ID and set all property values in this method.
app/Livewire/EditModal.php:
use App\Models\Product; class EditModal extends Component{ #[Locked] public int $id; public string $name = ''; public string $price = ''; public bool $showModal = false; public function edit($productId): void { $product = Product::find($productId); $this->id = $product->id; $this->name = $product->name; $this->price = $product->price; $this->showModal = true; } // ...}
resources/views/livewire/edit-model.blade.php:
// ...<td class="px-6 py-4 text-sm leading-5 text-gray-900 whitespace-no-wrap"> <a href="#" class="mt-4 rounded-md bg-gray-800 px-4 py-2 text-xs font-semibold uppercase tracking-widest text-white hover:bg-gray-700"> <a wire:click="edit({{ $product->id }})" href="#" class="mt-4 rounded-md bg-gray-800 px-4 py-2 text-xs font-semibold uppercase tracking-widest text-white hover:bg-gray-700"> Edit </a></td>// ...
Now let's add a simple modal which will be shown when showModal
is set to true. This code needs to go after the table.
resources/views/livewire/edit-modal.blade.php:
<div> // ... <div @class(['fixed bottom-0 left-0 flex h-full w-full items-center justify-center bg-gray-800 bg-opacity-60', 'hidden' => ! $showModal])> <div class="w-1/2 rounded-lg bg-white"> <form wire:submit="update" class="w-full"> <div class="flex flex-col items-start p-4"> <div class="flex w-full items-center border-b pb-4"> <div class="text-lg font-medium text-gray-900">Edit Product</div> <svg wire:click="$toggle('showModal')" class="ml-auto h-6 w-6 cursor-pointer fill-current text-gray-700" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 18 18"> <path d="M14.53 4.53l-1.06-1.06L9 7.94 4.53 3.47 3.47 4.53 7.94 9l-4.47 4.47 1.06 1.06L9 10.06l4.47 4.47 1.06-1.06L10.06 9z"/> </svg> </div> <div class="mt-4 w-full"> <label for="name" class="block text-sm font-medium text-gray-700"> Name </label> <input wire:model="name" id="name" class="block mt-1 w-full rounded-md border border-gray-200 px-3 py-2 text-sm"/> </div> <div class="my-4 w-full border-b pb-4"> <label for="price" class="block text-sm font-medium text-gray-700"> Price </label> <input wire:model="price" id="price" class="block mt-1 w-full rounded-md border border-gray-200 px-3 py-2 text-sm"/> </div> <div class="ml-auto"> <button class="mt-2 rounded-md bg-blue-500 px-4 py-2 text-xs font-semibold uppercase tracking-widest text-white hover:bg-blue-700" type="submit"> Save </button> <button wire:click="$toggle('showModal')" class="mt-2 rounded-md bg-gray-800 px-4 py-2 text-xs font-semibold uppercase tracking-widest text-white hover:bg-gray-700" type="button"> Close </button> </div> </div> </form> </div> </div></div>
Take a look at the close buttons in the modal. We are using a magic action, $toggle
, to close the modal.