Todays tutorial will be on how to auto-populate a dropdown according to a preselected dropdown on Laravel using Ajax.
This tutorial is also available on github.
First of all, we’ll create a new Laravel project(I’m assuming you already have composer installed).You could call the project anything but I’ll just go with “autopopulate”.
composer create-project laravel/laravel autopopulate
Then open the .env file and adjust the database connection settings to match your database name and credentials.
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=autopopulate
DB_USERNAME=root
DB_PASSWORD=
For this tutorial, I’m going to using Countries and States.
Let’s create out model and migrations file for both.
Run
php artisan make:model Country -m
and then run
php artisan make:model State -m
For the country migrations file.
Schema::create(
'countries',
function (Blueprint $table) {
$table->id();
$table->string('name');
$table->timestamps();
}
);
For the state migrations file.
Schema::create(
'states',
function (Blueprint $table) {
$table->id();
$table->string('name');
$table->integer('country_id');
$table->timestamps();
}
);
We will create dummy data for both in our database.
Let’s create our factories for both.
Run
php artisan make:factory CountryFactory
and then run
php artisan make:factory StateFactory
For the country factory
<?php
/** @var \Illuminate\Database\Eloquent\Factory $factory */
use App\Country;
use Faker\Generator as Faker;
$factory->define(
Country::class,
function (Faker $faker) {
return [
'name' => $faker->word
];
}
);
For the state factory
<?php
/** @var \Illuminate\Database\Eloquent\Factory $factory */
use App\State;
use Faker\Generator as Faker;
$factory->define(
State::class,
function (Faker $faker) {
return [
'name' => $faker->word
];
}
);
In the database seeder
<?php
use App\Country;
use App\State;
use Illuminate\Database\Seeder;
class DatabaseSeeder extends Seeder
{
/**
* Seed the application's database.
*
* @return void
*/
public function run()
{
$countries = factory(Country::class, 20)->create();
$countries->each(
function ($country) {
factory(State::class, 35)->create(['country_id' => $country->id]);
}
);
}
}
Then run
php artisan migrate
and run
php artisan db:seed
At this point, your database has been populate with dummy data.
Then let’s create our controller to handle all our requests.
You can give your controller any name that suits your project
php artisan make:controller HomeController
Open your web.php file to register routes
Route::get('/', 'HomeController@index');
Route::get('/state/{countryId}', 'HomeController@getState');
In your Controller
<?php
namespace App\Http\Controllers;
use App\Country;
use App\State;
class HomeController extends Controller
{
/**
* Display page with all countries
*
* @return Illuminate\View\View
* @author Anthony Akro <anthonygakro@gmail.com> [a4anthony]
*/
public function index()
{
$countries = Country::all();
return view('welcome', ['countries' => $countries]);
}
/**
* Retrieves state details from database
*
* @param int $countryId
*
* @return Illuminate\Http\Response
* @author Anthony Akro <anthonygakro@gmail.com> [a4anthony]
*/
public function getState($countryId)
{
if (!$countryId) {
$html = '<option value="">' . trans('global.pleaseSelect') . '</option>';
} else {
$html = '<option value="' . '">' . '--- Select Sub Category ---' . '</option>';
$states = State::where('country_id', $countryId)->get();
foreach ($states as $state) {
$html .= '<option value="' . $state->id . '">' . $state->name . '</option>';
}
}
return response()->json(['html' => $html]);
}
}
In your welcome.blade.php file in the the Resources > view folder
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Laravel Autopopulate</title>
<!-- Fonts -->
<link href="https://fonts.googleapis.com/css?family=Nunito:200,600" rel="stylesheet">
<!-- jquery -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<!-- bootstrap -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>
<!-- Styles -->
<style>
html,
body {
background-color: #fff;
color: #636b6f;
font-family: 'Nunito', sans-serif;
font-weight: 200;
height: 100vh;
margin: 0;
}
.full-height {
height: 100vh;
}
.flex-center {
align-items: center;
display: flex;
justify-content: center;
}
.position-ref {
position: relative;
}
.top-right {
position: absolute;
right: 10px;
top: 18px;
}
.content {
text-align: center;
}
.title {
font-size: 84px;
}
.links>a {
color: #636b6f;
padding: 0 25px;
font-size: 13px;
font-weight: 600;
letter-spacing: .1rem;
text-decoration: none;
text-transform: uppercase;
}
.m-b-md {
margin-bottom: 30px;
}
</style>
</head>
<body>
<div class="flex-center position-ref full-height">
@if (Route::has('login'))
<div class="top-right links">
@auth
<a href="{{ url('/home') }}">Home</a>
@else
<a href="{{ route('login') }}">Login</a>
@if (Route::has('register'))
<a href="{{ route('register') }}">Register</a>
@endif
@endauth
</div>
@endif
<div class="content">
<div class="title m-b-md">
Laravel Autopopulate dropdown
</div>
<div style="padding:5rem;">
<div class="row">
<div class="col-6">
<div class="form-group">
<select name="country" id="country" class="form-control">
<option value="">-- select country --</option>
@foreach ($countries as $country)
<option value="{{$country->id}}">{{$country->name}}</option>
@endforeach
</select>
</div>
</div>
<div class="col-6">
<div class="form-group">
<select name="" id="state" class="form-control" disabled>
<option value="">-- select state --</option>
</select>
</div>
</div>
</div>
</div>
</div>
</div>
<script>
$(document).ready(function() {
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
$("#country").change(function() {
console.log($(this).val());
$.ajax({
url: "/state/" + $(this).val(),
method: 'GET',
success: function(data) {
$('#state').prop('disabled', false);
$('#state').html(data.html);
}
});
});
});
</script>
</body>
</html>
To test, run
php artisan serve
and open the url below in your browser
http://localhost:8000
I hope this helped.