Parent and Child Dropdown on Laravel Livewire V2

Updated: Feb 22, 2025

Parent and Child Dropdown on Laravel Livewire V2

To create a parent-child dropdown using Laravel Livewire V2, we'll build a simple example where we have a list of categories (parents), and under each category, we'll have some sub-categories (children). Here's a step-by-step guide to create this functionality:

  1. Set up the Laravel project and Livewire component:

First, make sure you have a Laravel project set up and installed Livewire. If you don't have it yet, follow the official Laravel Livewire installation guide: https://laravel-livewire.com/docs/2.x/installation

Create a new Livewire component called CategoriesComponent.php inside the app/Http/Livewire directory:

<?php

namespace App\Http\Livewire;

use Livewire\Component;

class CategoriesComponent extends Component
{
    public $selectedCategory = null;

    public function render()
    {
        return view('livewire.categories');
    }
}
  1. Create the component view:

Create a new file called categories.blade.php inside the resources/views/livewire/ directory:

<div>
    <select wire:model="selectedCategory">
        <option value="">Select a category</option>
    </select>

    <livewire:component :name="'sub-categories.' . ($selectedCategory ? str_slug($selectedCategory, '-') : 'index')" :key="$selectedCategory"></livewire:component>
</div>
  1. Set up the database:

Assuming you have a categories table with the following columns: id, name, and parent_id (null for top-level categories). Create a migration if you don't have it yet:

php artisan make:model Category -m
php artisan make:controller CategoryController --resource

Update the Category model:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Category extends Model
{
    //
}

Update the CategoryController:

<?php

namespace App\Http\Controllers;

use App\Category;

class CategoryController extends Controller
{
    public function index()
    {
        return view('categories.index');
    }

    public function getCategories()
    {
        return response()->json(Category::with('children')->get());
    }
}

Update the routes/web.php:

Route::get('/categories', 'CategoryController@index')->name('categories.index');
Route::get('/categories/get-categories', 'CategoryController@getCategories')->name('categories.get-categories');
  1. Implement the parent-child dropdown:

Update the CategoriesComponent.php:

<?php

namespace App\Http\Livewire;

use Livewire\Component;
use App\Category;

class CategoriesComponent extends Component
{
    public $selectedCategory = null;

    public function render()
    {
        return view('livewire.categories');
    }

    public function getCategories()
    {
        $this->categories = Category::all();
    }

    public function updatedSelectedCategory()
    {
        $this->reset('subCategories');

        if ($this->selectedCategory) {
            $this->subCategories = Category::where('parent_id', $this->selectedCategory->id)->get();
        }
    }
}

Update the categories.blade.php:

<div>
    <select wire:model="selectedCategory" @change="updatedSelectedCategory()">
        <option value="">Select a category</option>
        @foreach ($categories as $category)
            <option value="{{ $category->id }}">{{ $category->name }}</option>
        @endforeach
    </select>

    <livewire:component :name="'sub-categories.' . ($selectedCategory ? str_slug($selectedCategory->name, '-') : 'index')" :key="$selectedCategory"></livewire:component>
</div>

@push('scripts')
<script>
    document.addEventListener('livewire:load', () => {
        @this.getCategories();
    });
</script>
@endpush

Create a new file called SubCategoriesComponent.php inside the app/Http/Livewire directory:

<?php

namespace App\Http\Livewire;

use Livewire\Component;
use App\Category;

class SubCategoriesComponent extends Component
{
    public function render()
    {
        return view('livewire.sub-categories');
    }

    public function renderSubCategories()
    {
        return view('livewire.sub-categories');
    }

    public function mount($category)
    {
        $this->category = $category;
    }

    public function getSubCategoriesProperty()
    {
        return $this->category ? $this->category->children : [];
    }
}

Create a new file called sub-categories.blade.php inside the resources/views/livewire/ directory:

<ul>
    @foreach ($subCategories as $subCategory)
        <li>{{ $subCategory->name }}</li>
    @endforeach
</ul>
  1. Test the component:

Run the Laravel development server and visit http://localhost:8000/categories to test the parent-child dropdown functionality.

This example demonstrates how to create a simple parent-child dropdown using Laravel Livewire V2. You can extend this example to handle more complex scenarios, such as adding or deleting categories and sub-categories, or implementing cascading dropdowns.