Now let's create a real dynamic thing with Livewire: a Modal to show the form to create a category.
Also, we will make the Slug field automatically generated after we change the Name field.
First, we will add the modal itself with form. In the resources/livewire/categories-list.blade.php
just before last </div>
, add this code:
// <div class="@if (!$showModal) hidden @endif flex items-center justify-center fixed left-0 bottom-0 w-full h-full bg-gray-800 bg-opacity-90"> <div class="w-1/2 bg-white rounded-lg"> <form wire:submit.prevent="save" class="w-full"> <div class="flex flex-col items-start p-4"> <div class="flex items-center pb-4 mb-4 w-full border-b"> <div class="text-lg font-medium text-gray-900">Create Category</div> <svg wire:click.prevent="$set('showModal', false)" class="ml-auto w-6 h-6 text-gray-700 cursor-pointer fill-current" 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="mb-2 w-full"> <label class="block text-sm font-medium text-gray-700" for="name"> Name </label> <input wire:model.live.debounce="name" id="name" class="py-2 pr-4 pl-2 mt-2 w-full text-sm rounded-lg border border-gray-400 sm:text-base focus:outline-none focus:border-blue-400" /> @error('name') <span class="text-sm text-red-500">{{ $message }}</span> @enderror </div> <div class="mb-2 w-full"> <label class="block text-sm font-medium text-gray-700" for="slug"> Slug </label> <input wire:model="slug" id="slug" class="py-2 pr-4 pl-2 mt-2 w-full text-sm rounded-lg border border-gray-400 sm:text-base focus:outline-none focus:border-blue-400" /> @error('slug') <span class="text-sm text-red-500">{{ $message }}</span> @enderror </div> <div class="mt-4 ml-auto"> <button class="px-4 py-2 font-bold text-white bg-blue-500 rounded hover:bg-blue-700" type="submit"> Create </button> <button wire:click="$set('showModal', false)" class="px-4 py-2 font-bold text-white bg-gray-500 rounded" type="button" data-dismiss="modal"> Close </button> </div> </div> </form> </div> </div> </div>
As you can see, in the modal we have the $showModal
variable and binded form inputs to name
and slug
. In the CategoriesList
component, we need to add public properties for them.
app/Livewire/CategoriesList.php:
class CategoriesList extends Component{ use WithPagination; public ?Category $category = null; public string $name = ''; public string $slug = ''; public bool $showModal = false; public function render(): View { $categories = Category::paginate(10); return view('livewire.categories-list', [ 'categories' => $categories, ]); }}
To open the modal, first, add the wire:click
action to the Add Category
button.
resources/livewire/categories-list.blade.php:
<x-primary-button wire:click="openModal" type="button" class="mb-4"> Add Category</x-primary-button>
When the button is clicked, the openModal
method in the Livewire component will be called. In this method, we set $showModal
to true.
app/Livewire/CategoriesList.php:
class CategoriesList extends Component{ use WithPagination; public Category $category; public bool $showModal = false; public function openModal(): void { $this->showModal = true; } public function render(): View { $categories = Category::paginate(10); return view('livewire.categories-list', [ 'categories' => $categories, ]); }}
Now, after clicking Add Category
, you will see the modal with the form.
Before creating a category, let's add validation to the form. For this, we will use the rules()
method in the Livewire component.
class CategoriesList extends Component{ use WithPagination; // ... protected function rules(): array { return [ 'name' => ['required', 'string', 'min:3'], 'slug' => ['nullable', 'string'], ]; } }
For the slug field, we will generate it automatically from the name. To achieve this, we will use Livewire Lifecycle Hooks.
app/Http/Livewire/CategoriesList.php:
use Illuminate\Support\Str; class CategoriesList extends Component{ use WithPagination; // ... public function updatedName(): void { $this->slug = Str::slug($this->name); } // ...}
Now, saving the category.
In the form we added a Livewire Action wire:submit="save"
, which means when the Create
button is pressed, the save()
method in Livewire Component will be called.
class CategoriesList extends Component{ // ... public function save() { $this->validate(); Category::create($this->only('name', 'slug')); $this->reset('showModal'); } }
Here, we first validate and then save the category to the DB. After that, we set the $showModal
to its initial value which is false
.
A new category is created successfully, yay!