Back to Course |
Practical Livewire 3: Order Management System Step-by-Step

Create New Category Modal

Now let's create a real dynamic thing with Livewire: a Modal to show the form to create a category.

create category modal

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.

create category modal

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);
}
 
// ...
}

create category form with auto slug

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!

new category created