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.
Contents
- Add Database configuration
- Create Tables
- Create Models
- Create Controller
- Create Route
- Create Livewire Component
- Create View
- Output
- 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 countries
, states
, and cities
tables using migration.
I am adding foreign key on states
and cities
tables.
states
table is linked tocountries
table, andcities
table is linked tostates
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
indatabase/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
indatabase/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
, andname
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
, andname
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.
- index() – Load
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 thestates
table wherecountry_id
is equals to$this->country_id
. Assign fetched records to$this->states
.
- mount() – It is inbuilt method to load initial data. Fetch all
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 thecities
table wherestate_id
is equals to$this->state_id
. Assign fetched records to$this->cities
.
- getStateCities() – This method is called when
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
. Addingcountry_id
model andchange
event that callsgetCountryStates
. - 2nd is for state selection. Add state list if
$states
is not empty. Addingstate_id
model andchange
event that callsgetStateCities
. - 3rd is for city selection. Add city list if
$cities
is not empty. Addingcity_id
model.
- 1st is for country selection. Add country list by looping on
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
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.