You can populate dropdown values based on the action of another dropdown. This type of functionality comes under dependency on the other event. The event can be any like click, submit, change, etc. If you have more than one dropdown and you want to make it dependent then you can create it. You can create n number of dependent dropdowns and populate the values correspondingly. In this post, we will be creating a dependent dropdown in Laravel 8. For populating the dropdown options, we will use Ajax request. Through the first dropdown change event, we will send the Ajax request to the server. Then we will populate the next dropdown values based on the response.
Prerequisites
Before moving forward to this demo, please make sure, you are ready to create a new application in Laravel 8. Your system must meet the following requirements-
- PHP >= 7.3
- MySQL (version > 5)
- Apache/Nginx Server
- VS Code Editor
- Composer
Before, going to create an application, let me give an overview of what will we implement here. In this application, we will create two dropdowns. The first dropdown will contain the name of a few programming languages. Then on the selection of a programming language, we will populate its frameworks in the second dropdown.
Once, you are ready, let’s create a new project set up in Laravel 8.
Create Application For Dependent Dropdown in Laravel 8
For creating the new project setup, I will use composer. Using composer, we can create the Laravel application. Therefore, open the terminal and hit the below command.
composer create-project --prefer-dist laravel/laravel dependent-dropdown
When your application is created, let’s set up the database and configure it.
Create and Configure MySQL Database in Laravel 8
For creating the database, open the MySQL terminal and hit the below command.
CREATE DATABASE dependent_dropdown
After creating the database, let’s configure it in the Laravel 8 application. Navigate to the .env file. Under the DB section, you will have to configure as shown below.
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=dependent_dropdown
DB_USERNAME=root
DB_PASSWORD=root
Now, your application is ready for database operations. Hence, let’s create the models and migrations for managing dependent dropdown functionalities.
Create Model and Migration For Dependent Dropdown
For this application, you will require two models and migrations. Open the terminal and hit the below command.
php artisan make:model Language -m
AND
php artisan make:model Framework -m
The above command will create models and migrations respectively for Language and Framework.
After creating the migrations, let’s add the schema in both files one by one as shown below.
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateLanguagesTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('languages', function (Blueprint $table) {
$table->id();
$table->string('name')->nullable();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('languages');
}
}
Similarly, add the schema in the frameworks table as shown below.
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateFrameworksTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('frameworks', function (Blueprint $table) {
$table->id();
$table->string('name')->nullable();
$table->unsignedBigInteger('language_id')->nullable();
$table->foreign('language_id')->references('id')->on('languages')->onDelete('cascade');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('frameworks');
}
}
After adding the schemas to both tables, you will need to dump them. For dumping the schema in the database, you will need to migrate the tables.
php artisan migrate
The above command will migrate the schemas.
Add Mass Assignment in Models
We have two models, add the fillable array one by one in both models.
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Language extends Model
{
use HasFactory;
protected $fillable = [
'name'
];
}
Similarly, add in the second model (Framework.php).
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Framework extends Model
{
use HasFactory;
protected $fillable = [
'name', 'language_id'
];
}
In the next step, I will create a seeder class for seeding data into both tables using the model.
Create Seeder in Laravel 8
Stay ahead on the terminal and hit the below command.
php artisan make:seeder LanguageSeeder
The command will generate a seeder file named LanguageSeeder.php in database/seeders folder. After creating the file, let’s add the below snippet there.
<?php
namespace Database\Seeders;
use App\Models\Framework;
use App\Models\Language;
use Illuminate\Database\Seeder;
class LanguageSeeder extends Seeder
{
/**
* Run the database seeds.
*
* @return void
*/
public function run()
{
$dataArray = array(
'PHP' => [
'CodeIgniter',
'Laravel',
'Yii',
'Cake PHP',
'Symfony',
'Phalcon'
],
'Python' => [
'DJango',
'Flask',
'CherryPy',
'web2py',
'Bottle',
'TurboGears'
],
'Java' => [
'Spring',
'Hibernate',
'JSF',
'GWT',
'Struts',
'Blade'
],
'JavaScript' => [
'React',
'Angular',
'Vue',
'Svelte',
'Preact',
'Backbone',
'Node',
'Next',
'Express',
'Nuxt',
'Meteor'
],
);
foreach ($dataArray as $language => $frameworks) {
$language = Language::create([
'name' => $language
]);
if ($language) {
foreach ($frameworks as $key => $framework) {
Framework::create([
'language_id' => $language->id,
'name' => $framework
]);
}
}
}
}
}
In the above snippet, I have created a static array with some data for language and its framework. Using the iteration, it will insert the language into the languages table and return the id of that language. Now, I passed that id along with the framework name in the next iteration. It will insert into the frameworks table.
Now, run this seeder file using the below command.
php artisan db:seed --class LanguageSeeder
This command will run the snippet for inserting values in the languages and the frameworks table.
You can check the result in your database. I have data in the languages table now.
Similarly, the frameworks table has data as well.
Now, we will move to the functionality implementation for the dependent dropdown.
Create a View For Adding Dependent Dropdown
For adding dropdowns we will need to have a form. In the form, we will add two dropdowns for Languages and frameworks. Initially, in the first dropdown, we will list out the values. But the second dropdown will be dependent on the selection of the first one.
Here, I have created a view named dropdowns.blade.php.
<!doctype html>
<html lang="en">
<head>
<title> Dependent Dropdown </title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"
integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<script src="https://code.jquery.com/jquery-3.6.0.min.js"
integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script>
<meta name="csrf-token" content="{{ csrf_token() }}" />
</head>
<body>
<div class="container mt-5">
<div class="row">
<div class="col-xl-6 col-lg-6 col-sm-12 col-12 m-auto">
<div class="card shadow">
<div class="card-header">
<h4 class="card-title font-weight-bold"> Dependent Dropdowns in Laravel 8 </h4>
</div>
<div class="card-body">
<div class="form-group">
<label> Language </label>
<select class="form-control" name="language" id="language">
<option value="" selected disabled> Select </option>
@forelse ($languages as $language)
<option value="{{ $language->id }}">{{ $language->name }} </option>
@empty
@endforelse
</select>
</div>
<div class="form-group">
<label> Framework </label>
<select class="form-control" name="framework" id="framework">
<option> Select </option>
</select>
</div>
</div>
</div>
</div>
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"
integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous">
</script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"
integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous">
</script>
<script src="{{ asset('js/script.js') }}"></script>
</body>
</html>
Add some JavaScript code for rendering data based on change event. We already linked this script in our blade file.
$("#language").change(function () {
$.ajaxSetup({
headers: {
"X-CSRF-TOKEN": $('meta[name="csrf-token"]').attr("content"),
},
});
const langId = $(this).val();
$.ajax({
type: "POST",
url: "frameworks",
data: {
languageId: langId,
},
success: function (result) {
$("#framework").empty();
$("#framework").append(
'<option selected disabled value="">Select</option>'
);
if (result && result?.status === "success") {
result?.data?.map((framework) => {
const frameworks = `<option value='${framework?.id}'> ${framework?.name} </option>`;
$("#framework").append(frameworks);
});
}
},
error: function (result) {
console.log("error", result);
},
});
});
Now, we will create a controller for rendering this view.
Create Controller
I have created a controller using the below command.
php artisan make:controller DropdownController
After creating the controller, add the below snippets.
<?php
namespace App\Http\Controllers;
use App\Models\Framework;
use App\Models\Language;
use Illuminate\Http\Request;
class DropdownController extends Controller
{
/**
* load dropdowns blade
* @param NA
* @return view
*/
public function index() {
$languages = Language::all();
return view('dropdowns', compact('languages'));
}
/**
* Get all frameworks based on language
* @param request
* @return response
*/
public function getFrameworks(Request $request) {
if ($request->languageId) {
$frameworks = Framework::where('language_id', $request->languageId)->get();
if ($frameworks) {
return response()->json(['status' => 'success', 'data' => $frameworks], 200);
}
return response()->json(['status' => 'failed', 'message' => 'No frameworks found'], 404);
}
return response()->json(['status' => 'failed', 'message' => 'Please select language'], 500);
}
}
Now, we need a few routes to make the functions work.
Add Routes For Dependent Dropdown
Open the web.php file and add the below routes.
Route::get('dropdowns', [DropdownController::class, 'index']);
Route::post('frameworks', [DropdownController::class, 'getFrameworks']);
How to Create Custom Password Reset Link in Laravel 8
Result of Dependent Dropdown in Laravel
To check the dependent dropdown result, run the application. Switch to the added route.
In the first dropdown, you will have all the languages which will be loaded directly through the view. But the second dropdown will be empty. It will be populated only when you will select any option from the first dropdown.
Let’s select any option for example PHP in the first dropdown.
Now, in the second dropdown, you will have the available frameworks based on selected language in the first dropdown.
Final Words
We have implemented dependent dropdowns in Laravel 8 using Ajax. We have two dropdowns, based on the selection of the first dropdown, we populated the options in the second dropdown. That’s it for this post.
Leave a Reply