Back to Course |
Livewire 3 From Scratch: Practical Course

Edit Modal Window

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.

edit modal


Livewire Component

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>

products table


Showing Modal

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.