How to Auto populate dropdown using Livewire – Laravel

If you are using Laravel for your web development, then you may have come across a requirement to auto-populate a dropdown with the database data.

For example, you may have a form with a country field and you want to auto-populate the states field on the form based on the country selected by the user.

In this article, I show how to auto-populate a dropdown using Livewire in Laravel 9.

I am hoping you have already installed Livewire on your project if not then you can view my previous post for installation.

How to Auto populate dropdown using Livewire - Laravel


Contents

  1. Add Database configuration
  2. Create Tables
  3. Create Models
  4. Create Controller
  5. Create Route
  6. Create Livewire Component
  7. Create View
  8. Output
  9. Conclusion

1. Add Database configuration

Open .env file to update the database connection.

Specify the host, database name, username, and password.

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=tutorial
DB_USERNAME=root
DB_PASSWORD=

2. Create Tables

Create countriesstates, and cities tables using migration.

I am adding foreign key on states and cities tables.

  • states table is linked to countries table, and
  • cities table is linked to states table.

You can learn foreign key implementation in detail from here.


  • Create Countries table –
php artisan make:migration create_countries_table
  • Now, navigate to database/migrations/ folder from the project root.
  • Find a PHP file that ends with create_countries_table and open it.
  • Define the table structure in the up() method.
public function up()
{
    Schema::create('countries', function (Blueprint $table) {
        $table->id();
        $table->string('name');
        $table->timestamps();
    });
}

  • Create States table –
php artisan make:migration create_states_table
  • Similarly, find a PHP file that ends with create_states_table in database/migrations/ folder and open it.
  • Define the table structure in the up() method.
  • Adding foreign key to country_id field.
public function up()
{
    Schema::create('states', function (Blueprint $table) {
         $table->id();
         $table->unsignedBigInteger('country_id');
         $table->string('name');
         $table->timestamps();
         $table->foreign('country_id')
              ->references('id')->on('countries')->onDelete('cascade');
    });
}

  • Create Cities table –
php artisan make:migration create_cities_table
  • Similarly, find a PHP file that ends with create_cities_table in database/migrations/ folder and open it.
  • Define the table structure in the up() method.
  • Adding foreign key to states_id field.
public function up()
{
    Schema::create('cities', function (Blueprint $table) {
         $table->id(); 
         $table->unsignedBigInteger('state_id');
         $table->string('name');
         $table->foreign('state_id')
                  ->references('id')->on('states')->onDelete('cascade');
         $table->timestamps();
    });
}

  • Run the migration to create tables –
php artisan migrate

3. Create Models

Create Countries, States, and Cities models.

  • Create Countries Model.
php artisan make:model Countries
  • Open app/Models/Countries.php file.
  • Specify mass assignable Model attributes – name using the $fillable property.

Completed Code

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Countries extends Model
{
      use HasFactory;

      protected $fillable = [
          'name'
      ];
}

  • Create States Model.
php artisan make:model States
  • Open app/Models/States.php file.
  • Specify mass assignable Model attributes – country_id, and name using the $fillable property.

Completed Code

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class States extends Model
{
      use HasFactory;

      protected $fillable = [
           'country_id','name'
      ];
}

  • Create Cities Model.
php artisan make:model Cities
  • Open app/Models/Cities.php file.
  • Specify mass assignable Model attributes – state_id, and name using the $fillable property.

Completed Code

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Cities extends Model
{
      use HasFactory;

      protected $fillable = [
         'state_id','name'
      ];
}

4. Create Controller

  • Create PagesController controller.
php artisan make:controller PagesController
  • Open app\Http\Controllers\PagesController.php file.
  • Create 1 method –
    • index() – Load index view.

Completed Code

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class PagesController extends Controller
{
    public function index(){
        return view('index');
    }
}

5. Create Route

  • Open routes/web.php file.
  • Define 1 route –
    • / – Load index view.
<?php

use Illuminate\Support\Facades\Route;

use App\Http\Controllers\PagesController;

Route::get('/', [PagesController::class, 'index']);

6. Create Livewire Component

Create autopopulate-dropdown component –

php artisan make:livewire autopopulate-dropdown

This will create 2 files –

  • app/Http/Livewire/AutopopulateDropdown.php
  • resources/views/livewire/autopopulate-dropdown.blade.php

AutopopulateDropdown.php

  • Include Countries, States, and Cities Models.
  • In the component class create 6 property variables –
    • $countries – Store countries list.
    • $states – Store selected country states list.
    • $cities – Store selected state cities list.
    • $country_id – Use for data binding in country dropdown
    • $state_id – Use for data binding in state dropdown.
    • $city_id – Use for data binding in city dropdown.
  • Create 3 methods –
    • mount() – It is inbuilt method to load initial data. Fetch all countries table records and assign to $this->countries.
    • getCountryStates() – This method is called when change event trigger in the country dropdown. Fetch records from the states table where country_id is equals to $this->country_id. Assign fetched records to $this->states.

Remove data of $this->cities and assign 0 to $this->state_id and $this->city_id.

    • getStateCities() – This method is called when change event trigger in the state dropdown. Fetch records from the cities table where state_id is equals to $this->state_id. Assign fetched records to $this->cities.

Assign 0 to $this->city_id.

Completed Code

<?php

namespace App\Http\Livewire;

use Livewire\Component;
use App\Models\Countries;
use App\Models\States;
use App\Models\Cities;

class AutopopulateDropdown extends Component
{
     public $countries, $states, $cities;

     public $country_id = 0;
     public $state_id = 0;
     public $city_id = 0;

     public function mount(){
          $this->countries = Countries::orderby('name','asc')
                             ->select('*')
                             ->get();
     }

     // Fetch states of a country
     public function getCountryStates(){

          $this->states = States::orderby('name','asc')
                          ->select('*')
                          ->where('country_id',$this->country_id)
                          ->get();

          // Reset values 
          unset($this->cities);
          $this->state_id = 0;
          $this->city_id = 0;
     }

     // Fetch cities of a state
     public function getStateCities(){
          $this->cities = Cities::orderby('name','asc')
                          ->select('*')
                          ->where('state_id',$this->state_id)
                          ->get();

          // Reset value 
          $this->city_id = 0;
     }

     public function render(){
          return view('livewire.autopopulate-dropdown');
     } 
}

autopopulate-dropdown.blade.php

  • Create 3 <select > elements –
    • 1st is for country selection. Add country list by looping on $countries. Adding country_id model and change event that calls getCountryStates.
    • 2nd is for state selection. Add state list if $states is not empty. Adding state_id model and change event that calls getStateCities.
    • 3rd is for city selection. Add city list if $cities is not empty. Adding city_id model.

Completed Code

<div>
    <style type="text/css">
    table select{
         padding: 5px;
         min-width: 200px;
    }
    </style>

    <table>
        <tr>
            <td>Country</td>
            <td>
                <select wire:model="country_id" wire:change="getCountryStates">
                    <option value="0">-- Select Country --</option>
                    @foreach($countries as $country)
                         <option value="{{ $country->id }}">{{ $country->name }}</option>
                    @endforeach
                </select>
            </td>
        </tr>
        <tr>
            <td>State</td>
            <td>
                <select wire:model="state_id" wire:change="getStateCities">
                    <option value="0">-- Select State --</option>
                    @if(!empty($states))
                         @foreach($states as $state)
                              <option value="{{ $state->id }}">{{ $state->name }}</option>
                         @endforeach
                    @endif
                </select>
            </td>
        </tr>
        <tr>
            <td>City</td>
            <td>
                <select wire:model="city_id">
                    <option value="0">-- Select City --</option>
                    @if(!empty($cities))
                        @foreach($cities as $city)
                             <option value="{{ $city->id }}">{{ $city->name }}</option>
                        @endforeach
                    @endif
                </select>
            </td>
        </tr>
    </table>

</div>

7. Create View

Create index.blade.php file in resources/views/ folder.

Add autopopulate-dropdown component and livewire style and script.

Completed Code

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>How to Auto populate dropdown using Livewire - Laravel</title>

    @livewireStyles
</head>
<body>

    <livewire:autopopulate-dropdown />

    @livewireScripts
</body>
</html>

8. Output

View Output


9. Conclusion

Following the tutorial, you can control multiple dropdown data based on parent dropdown selection using Livewire.

If you found this tutorial helpful then don't forget to share.

Leave a Comment