article

Tuesday, December 3, 2024

Laravel Dynamic Dependent Dropdown | Country State City | Jquery AJAX

Laravel Dynamic Dependent Dropdown | Country State City | Jquery AJAX
Download Laravel App
https://laravel.com/docs/11.x/installation

Connecting our Database

open .env file root directory.

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=8889
DB_DATABASE=laravel11dev
DB_USERNAME=root
DB_PASSWORD=root
Database Migration

php artisan make:model Country -m
C:\xampp\htdocs\laravel\my-app>php artisan make:model Country -m
database/migrations/create_countries_table.php
Country
//database/migrations/create_countries_table.php
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
    /**
     * Run the migrations.
     */
    public function up() 
    {
        Schema::create('countries', function (Blueprint $table) {
            $table->id();
            $table->string('name');
        });
    }

    /**
     * Reverse the migrations.
     */
    public function down(): void
    {
        Schema::dropIfExists('countries');
    }
};
State
php artisan make:model State -m
C:\xampp\htdocs\laravel\my-app>php artisan make:model State -m
database/migrations/create_states_table.php
//<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
    /**
     * Run the migrations.
     */
    public function up()
    {
        Schema::create('states', function (Blueprint $table) {
            $table->id();
            $table->string('name');
            $table->integer('country_id');
        });
    }

    /**
     * Reverse the migrations.
     */
    public function down(): void
    {
        Schema::dropIfExists('states');
    }
};
City
php artisan make:model City -m
C:\xampp\htdocs\laravel\my-app>php artisan make:model City -m
database/migrations/create_cities_table.php
//database/migrations/create_cities_table.php
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
    /**
     * Run the migrations.
     */
    public function up()
    {
        Schema::create('cities', function (Blueprint $table) {
            $table->id();
            $table->string('name');
            $table->integer('state_id');
        });
    }

    /**
     * Reverse the migrations.
     */
    public function down(): void
    {
        Schema::dropIfExists('cities');
    }
};
SQL Database Table Counrty State and City : https://github.com/cairocodes/cairocoders/blob/main/country-state-city.sql

Create Controller

php artisan make:controller AccountController
C:\xampp\htdocs\laravel\my-app>php artisan make:controller AccountController
app/Http/Controllers/AccountController.php
//app/Http/Controllers/AccountController.php
<?php

namespace App\Http\Controllers;

use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Facades\DB;

class AccountController extends Controller
{
    public function index(){
        $countries = \DB::table('countries')->orderBy('name','ASC')->get();
        $data['countries'] = $countries;
        return view('users.create',$data);
    }

    public function fetchStates($country_id = null) {
        $states = \DB::table('states')->where('country_id',$country_id)->get();

        return response()->json([
            'status' => 1,
            'states' => $states
        ]);
    }

    public function fetchCities($state_id = null) {
        $cities = \DB::table('cities')->where('state_id',$state_id)->get();

        return response()->json([
            'status' => 1,
            'cities' => $cities
        ]);
    }

    public function save(Request $request){

        $validator = Validator::make($request->all(),[
            'name' => 'required',
            'email' => 'required|email'
        ]);

        if ($validator->passes()) {

            User::create([
                'name' => $request->name,
                'email' => $request->email,
                'password' => "123456",
                'country' => $request->country,
                'state' => $request->state,
                'city' => $request->city,
            ]);

            $request->session()->flash('success','User added successfully.');

            return response()->json([
                'status' =>  1                
            ]);

        } else {
            // return error 

            return response()->json([
                'status' =>  0,
                'errors' => $validator->errors()
            ]);
        }

    }

    public function list() {
        $users = DB::table('users')->get();
        $data['users'] = $users;
        return view('users.list',$data);
    }

    public function edit($id) {
        $user = User::where('id',$id)->first();

        $countries = \DB::table('countries')->orderBy('name','ASC')->get();
        $data['countries'] = $countries;


        $states = \DB::table('states')->where('country_id',$user->country)->orderBy('name','ASC')->get();        
        $data['states'] = $states;

        $cities = \DB::table('cities')->where('state_id',$user->state)->orderBy('name','ASC')->get();        
        $data['cities'] = $cities;

        if ($user == null ) {
            return redirect(url('/list'));
        }

        $data['user'] = $user;

        return view('users.edit',$data);
    }


    public function update($id, Request $request){

        $user = User::find($id);

        if($user == null) {

            $request->session()->flash('error','Enither user deleted or not found.');

            return response()->json([
                'status' =>  '400'                
            ]);
        }

        $validator = Validator::make($request->all(),[
            'name' => 'required',
            'email' => 'required|email'
        ]);

        if ($validator->passes()) {
            $user->name = $request->name;
            $user->email = $request->email;
            $user->country = $request->country;
            $user->state = $request->state;
            $user->city = $request->city;
            $user->save(); 

            $request->session()->flash('success','User updated successfully.');

            return response()->json([
                'status' =>  1                
            ]);

        } else {
            // return error 

            return response()->json([
                'status' =>  0,
                'errors' => $validator->errors()
            ]);
        }

    }
}
Routes
routes/web.php
//routes/web.php
<?php

use Illuminate\Support\Facades\Route;
use App\Http\Controllers\AccountController;

Route::get('/', function () {
    return view('welcome');
});

Route::get('/create', [AccountController::class, 'index']);
Route::post('/fetch-states/{id}', [AccountController::class, 'fetchStates']);
Route::post('/fetch-cities/{id}', [AccountController::class, 'fetchCities']);

Route::post('/save', [AccountController::class, 'save']);
Route::get('/list', [AccountController::class, 'list']);

Route::get('/edit/{id}', [AccountController::class, 'edit']);
Route::post('/edit/{id}', [AccountController::class, 'update']);
View Blade File resources/views/users/create.blade.php
//resources/views/users/create.blade.php
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Dynamic Dependent Dropdown</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
    <meta name="_token" content="{{ csrf_token() }}">
</head>

<body>
    <div class="bg p-3 shadow-lg text-center">
        <h4>Laravel Dynamic Dependent Dropdown | Country State City | Jquery AJAX</h4>
    </div>
    <div class="container mt-3">
        <div class="row d-flex justify-content-center">
            <div class="col-md-6">
                <a href="{{ url('/list') }}" class="btn btn-primary mb-3">Back</a>
                <div class="card card-primary p-4 border-0 shadow-lg">
                    <form action="" id="frm" name="frm" method="post">
                        <div class="card-body">
                            <h3>Create User</h3>
                            <div class="mb-3">
                                <input type="text" class="form-control-lg form-control" name="name" id="name" placeholder="Enter Name">
                                <p class="invalid-feedback" id="name-error"></p>
                            </div>
                            <div class="mb-3">
                                <input type="text" class="form-control-lg form-control" name="email" id="email" placeholder="Enter Email">
                                <p class="invalid-feedback" id="email-error"></p>
                            </div>
                            <div class="mb-3">
                                <select name="country" id="country" class="form-control-lg form-select">
                                    <option value="">Select Country</option>
                                    @if (!empty($countries))
                                    @foreach ($countries as $country)
                                    <option value="{{ $country->id }}">{{ $country->name }}</option>
                                    @endforeach
                                    @endif
                                </select>
                            </div>

                            <div class="mb-3">
                                <select name="state" id="state" class="form-control-lg form-select">
                                    <option value="">Select State</option>
                                </select>
                            </div>

                            <div class="mb-3">
                                <select name="city" id="city" class="form-control-lg form-select">
                                    <option value="">Select City</option>
                                </select>
                            </div>

                            <div class="d-grid">
                                <button class="btn btn-primary btn-lg">Create</button>
                            </div>
                        </div>
                    </form>
                </div>
            </div>
        </div>
    </div>
    <script src="https://code.jquery.com/jquery-3.7.1.min.js"></script> <!--https://blog.jquery.com/2023/08/28/jquery-3-7-1-released-reliable-table-row-dimensions/ https://getbootstrap.com/ -->
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz" crossorigin="anonymous"></script>
    <script>
        $.ajaxSetup({
            headers: {
                'X-CSRF-TOKEN': $('meta[name="_token"]').attr('content')
            }
        });

        $(document).ready(function() {
            $("#country").change(function() {
                var country_id = $(this).val();

                if (country_id == "") {
                    var country_id = 0;
                }
                //alert(country_id);
                $.ajax({
                    url: '{{ url("/fetch-states/") }}/' + country_id,
                    type: 'post',
                    dataType: 'json',
                    success: function(response) {
                        $('#state').find('option:not(:first)').remove();
                        $('#city').find('option:not(:first)').remove();

                        if (response['states'].length > 0) {
                            $.each(response['states'], function(key, value) {
                                $("#state").append("<option value='" + value['id'] + "'>" + value['name'] + "</option>")
                            });
                        }
                    }
                });
            });


            $("#state").change(function() {
                var state_id = $(this).val();

                //console.log(state_id);

                if (state_id == "") {
                    var state_id = 0;
                }

                $.ajax({
                    url: '{{ url("/fetch-cities/") }}/' + state_id,
                    type: 'post',
                    dataType: 'json',
                    success: function(response) {
                        $('#city').find('option:not(:first)').remove();

                        if (response['cities'].length > 0) {
                            $.each(response['cities'], function(key, value) {
                                $("#city").append("<option value='" + value['id'] + "'>" + value['name'] + "</option>")
                            });
                        }
                    }
                });
            });

        });

        $("#frm").submit(function(event) {
            event.preventDefault();
            $.ajax({
                url: '{{ url("/save") }}',
                type: 'post',
                data: $("#frm").serializeArray(),
                dataType: 'json',
                success: function(response) {
                    alert(response['status']);
                    if (response['status'] == 1) {
                        window.location.href = "{{ url('list') }}";
                    } else {
                        if (response['errors']['name']) {
                            $("#name").addClass('is-invalid');
                            $("#name-error").html(response['errors']['name']);
                        } else {
                            $("#name").removeClass('is-invalid');
                            $("#name-error").html("");
                        }

                        if (response['errors']['email']) {
                            $("#email").addClass('is-invalid');
                            $("#email-error").html(response['errors']['email']);
                        } else {
                            $("#email").removeClass('is-invalid');
                            $("#email-error").html("");
                        }
                    }
                }
            });
        })
    </script>
</body>

</html>
resources/views/users/edit.blade.php
//resources/views/users/edit.blade.php
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Dynamic Dependent Dropdown</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
    <meta name="_token" content="{{ csrf_token() }}">
</head>

<body>
    <div class="bg p-3 text-white shadow-lg text-center">
        <h4>Laravel Dynamic Dependent Dropdown Tutorial</h4>
    </div>
    <div class="container mt-3">
        <div class="row d-flex justify-content-center">
            <div class="col-md-6">
                <a href="{{ url('/list') }}" class="btn btn-primary mb-3">Back</a>
                <div class="card card-primary p-4 border-0 shadow-lg">
                    <form action="" id="frm" name="frm" method="post">
                        <div class="card-body">
                            <h3>Edit User</h3>
                            <div class="mb-3">
                                <input type="text" class="form-control-lg form-control" name="name" id="name" placeholder="Enter Name" value="{{ $user->name }}">
                                <p class="invalid-feedback" id="name-error"></p>
                            </div>
                            <div class="mb-3">
                                <input type="text" class="form-control-lg form-control" name="email" id="email" placeholder="Enter Email" value="{{ $user->email }}">
                                <p class="invalid-feedback" id="email-error"></p>
                            </div>
                            <div class="mb-3">
                                <select name="country" id="country" class="form-control-lg form-select">
                                    <option value="">Select Country</option>
                                    @if (!empty($countries))
                                    @foreach ($countries as $country)
                                    <option {{ ($user->country == $country->id) ? 'selected' : '' }} value="{{ $country->id }}">{{ $country->name }}</option>
                                    @endforeach
                                    @endif
                                </select>
                            </div>

                            <div class="mb-3">
                                <select name="state" id="state" class="form-control-lg form-select">
                                    <option value="">Select State</option>
                                    @if (!empty($states))
                                    @foreach ($states as $state)
                                    <option {{ ($user->state == $state->id) ? 'selected' : '' }} value="{{ $state->id }}">{{ $state->name }}</option>
                                    @endforeach
                                    @endif
                                </select>
                            </div>

                            <div class="mb-3">
                                <select name="city" id="city" class="form-control-lg form-select">
                                    <option value="">Select City</option>
                                    @if (!empty($cities))
                                    @foreach ($cities as $city)
                                    <option {{ ($user->city == $city->id) ? 'selected' : '' }} value="{{ $city->id }}">{{ $city->name }}</option>
                                    @endforeach
                                    @endif
                                </select>
                            </div>

                            <div class="d-grid">
                                <button class="btn btn-primary btn-lg">Update</button>
                            </div>
                        </div>
                    </form>
                </div>
            </div>
        </div>
    </div>

    <script src="https://code.jquery.com/jquery-3.7.1.min.js"></script> <!--https://blog.jquery.com/2023/08/28/jquery-3-7-1-released-reliable-table-row-dimensions/ https://getbootstrap.com/ -->
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz" crossorigin="anonymous"></script>
    <script>
        $.ajaxSetup({
            headers: {
                'X-CSRF-TOKEN': $('meta[name="_token"]').attr('content')
            }
        });

        $(document).ready(function() {
            $("#country").change(function() {
                var country_id = $(this).val();

                if (country_id == "") {
                    var country_id = 0;
                }

                $.ajax({
                    url: '{{ url("/fetch-states/") }}/' + country_id,
                    type: 'post',
                    dataType: 'json',
                    success: function(response) {
                        $('#state').find('option:not(:first)').remove();
                        $('#city').find('option:not(:first)').remove();

                        if (response['states'].length > 0) {
                            $.each(response['states'], function(key, value) {
                                $("#state").append("<option value='" + value['id'] + "'>" + value['name'] + "</option>")
                            });
                        }
                    }
                });
            });


            $("#state").change(function() {
                var state_id = $(this).val();

                console.log(state_id);

                if (state_id == "") {
                    var state_id = 0;
                }

                $.ajax({
                    url: '{{ url("/fetch-cities/") }}/' + state_id,
                    type: 'post',
                    dataType: 'json',
                    success: function(response) {
                        $('#city').find('option:not(:first)').remove();

                        if (response['cities'].length > 0) {
                            $.each(response['cities'], function(key, value) {
                                $("#city").append("<option value='" + value['id'] + "'>" + value['name'] + "</option>")
                            });
                        }
                    }
                });
            });

        });

        $("#frm").submit(function(event) {
            event.preventDefault();
            $.ajax({
                url: '{{ url("/edit/".$user->id) }}',
                type: 'post',
                data: $("#frm").serializeArray(),
                dataType: 'json',
                success: function(response) {
                    if (response['status'] == 1) {
                        window.location.href = "{{ url('list') }}";
                    } else {
                        if (response['errors']['name']) {
                            $("#name").addClass('is-invalid');
                            $("#name-error").html(response['errors']['name']);
                        } else {
                            $("#name").removeClass('is-invalid');
                            $("#name-error").html("");
                        }

                        if (response['errors']['email']) {
                            $("#email").addClass('is-invalid');
                            $("#email-error").html(response['errors']['email']);
                        } else {
                            $("#email").removeClass('is-invalid');
                            $("#email-error").html("");
                        }
                    }
                }
            });
        })
    </script>
</body>

</html>
resources/views/users/list.blade.php
//resources/views/users/list.blade.php
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Dynamic Dependent Dropdown</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
    <meta name="_token" content="{{ csrf_token() }}">
</head>

<body>
    <div class="bg p-3 text-white shadow-lg text-center">
        <h4>Laravel Dynamic Dependent Dropdown Tutorial</h4>
    </div>
    <div class="container mt-3">
        <div class="row d-flex justify-content-center">
            <div class="col-md-6">
                <a href="{{ url('/create') }}" class="btn btn-primary mb-3">Create</a>
                <div class="card card-primary p-4 border-0 shadow-lg">

                    @if(Session::has('success'))
                    <div class="alert alert-success">
                        {{ Session::get('success') }}
                    </div>
                    @endif

                    @if(Session::has('error'))
                    <div class="alert alert-danger">
                        {{ Session::get('error') }}
                    </div>
                    @endif

                    <div class="card-body">
                        <h3>Users</h3>
                        <table class="table">
                            <thead>
                                <tr>
                                    <th>ID</th>
                                    <th>Name</th>
                                    <th>Email</th>
                                    <th>Edit</th>
                                </tr>

                                @if (!empty($users))
                                @foreach ($users as $user)
                                <tr>
                                    <td>{{ $user->id }}</td>
                                    <td>{{ $user->name }}</td>
                                    <td>{{ $user->email }}</td>
                                    <td>
                                        <a href="{{ url('edit/'.$user->id) }}" class="btn btn-success">Edit</a>
                                    </td>
                                </tr>
                                @endforeach
                                @endif

                            </thead>
                        </table>
                    </div>

                </div>
            </div>
        </div>
    </div>
    <script src="https://code.jquery.com/jquery-3.7.1.min.js"></script> <!--https://blog.jquery.com/2023/08/28/jquery-3-7-1-released-reliable-table-row-dimensions/ https://getbootstrap.com/ -->
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz" crossorigin="anonymous"></script>
    </body> 
    </html>
Run C:\xampp\htdocs\laravel\my-app>php artisan serve
Starting Laravel development server: http://127.0.0.1:8000

Related Post