Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Laravel dynamic dropdown country and state

I'm trying to make two dropdown menus. These are the countries and states selections from my database. My problem is don't know how to make conditions that states must be dependent on countries. When I select [countryname] it will give a different selection of states name in my dropdown. So far here what I have done so far.

AdminController.php

public function user_register()
    {
        $countryname = DB::table('countries')
            ->get();
        $statename = DB::table('states')
            ->get();

        $title = ucwords(Lang::get('constants.user') . ' ' . Lang::get('constants.register')); 
        return View::make('register.user_register')
            ->with('title', $title)
            ->with('page', 'user_register')
            ->with('countryname', $countryname)
            ->with('statename', $statename)
    }

user_register.blade.php

<select class="form-control" id="countries" name="countries">
    <option value="">Please select</option>
        <?php foreach ($countryname as $key=>$countryname): ?>
        <option value="<?php echo $countryname->sortname; ?>"<?php
         if (isset($countries) && Input::old('countries') == $countryname->sortname) 
         {
             echo 'selected="selected"';
         }
         ?>>
         <?php  echo $countryname->sortname ." - ". $countryname->name  ; ?>
    </option>
    <?php endforeach; ?>
</select>


<select class="form-control" id="states" name="states">
    <option value="">Please select</option>
        <?php foreach ($statename as $key=>$statename): ?>
        <option value="<?php echo $countryname->name; ?>" <?php
        if (isset($states) && Input::old('states') == $statename->name)
        {
            echo 'selected="selected"';
        }
        ?>>
        <?php  echo $statename->name; ?></option>
        <?php endforeach; ?>
</select>

In my database

Table: countries

+-----------+--------------+------+-----+---------+----------------+
| Field     | Type         | Null | Key | Default | Extra          |
+-----------+--------------+------+-----+---------+----------------+
| country_id| int(11)      | NO   | PRI | NULL    | auto_increment |
| sortname  | varchar(3)   | NO   |     | NULL    |                |
| name      | varchar(150) | NO   |     | NULL    |                |
| phonecode | int(11)      | NO   |     | NULL    |                |
+-----------+--------------+------+-----+---------+----------------+

Table: states

+------------+------------------+------+-----+---------+----------------+
| Field      | Type             | Null | Key | Default | Extra          |
+------------+------------------+------+-----+---------+----------------+
| id         | int(10) unsigned | NO   | PRI | NULL    | auto_increment |
| name       | varchar(255)     | NO   |     | NULL    |                |
| country_id | int(11)          | NO   |     | NULL    |                |
+------------+------------------+------+-----+---------+----------------+
like image 891
Kevin Avatar asked Jul 12 '17 14:07

Kevin


2 Answers

Here's how to do a dynamic dropdown in Laravel:

You can see a demo of how it works here https://www.dronejobs.co/

Disclaimer: I didn't test this but it should work. Feel free to comment and I'll update ๐Ÿ™

app/Http/Controllers/HomeController.php

<?php

namespace App\Http\Controllers;

use App\{Country, State};

class HomeController extends Controller
{
    public function index()
    {
        return view('home', [
            'countries' => Country::all(),
            'states' => State::all(),
        ]);
    }
}

resources/views/home.blade.php

<select name="country">
    @foreach ($countries as $country)
        <option value="{{ $country->id }}">{{ $country->name }}</option>
    @endforeach
</select>

<select name=โ€œstateโ€>
    @foreach ($states as $state)
        <option value="{{ $state->id }}">{{ $state->name }}</option>
    @endforeach
</select>

<script>
    $(function() {
        $('select[name=country]').change(function() {

            var url = '{{ url('country') }}' + $(this).val() + '/states/';

            $.get(url, function(data) {
                var select = $('form select[name= state]');

                select.empty();

                $.each(data,function(key, value) {
                    select.append('<option value=' + value.id + '>' + value.name + '</option>');
                });
            });
        });
    });
</script>

app/Country.php

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Country extends Model
{   
    public function states()
    {
        return $this->hasMany('App\State');
    }

app/State.php

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

Class State extends Model
{   
    public function country()
    {
        return $this->belongsTo('App\Country');
    }

routes/web.php

Route::get('country/{country}/states', 'CountryController@getStates');

app/Http/Controllers/CountryController.php

<?php

namespace App\Http\Controllers;

use App\Country;

class CountryController extends Controller
{
    public function getStates(Country $country)
    {
        return $country->states()->select('id', 'name')->get();
    }
}
like image 89
tompec Avatar answered Nov 15 '22 18:11

tompec


I would like to update this post, I have already solved my problem. I just want to share this solutions for the community :)

I just added some ajax codes for this in my user_register.blade.php:

<div class="form-group">
    <label for="title">Select Country:</label>
    <select name="country" class="form-control">
        <option value="">--- Select country ---</option>
        @foreach ($countries as $key => $value)
            <option value="{{ $value }}">{{ $value }}</option>
        @endforeach
    </select>
</div>
<div class="form-group">
    <label for="title">Select state:</label>
    <select name="state" class="form-control">
    </select>
</div>
<script type="text/javascript">
$(document).ready(function() {
$('select[name="country"]').on('change', function() {
    var countryID = $(this).val();
        if(countryID) {
        $.ajax({
            url: '/admin/user_register/ajax/'+encodeURI(countryID),
            type: "GET",
            dataType: "json",
            success:function(data) {
            $('select[name="state"]').empty();
            $.each(data, function(key, value) {
                $('select[name="state"]').append('<option value="'+ value +'">'+ value +'</option>');
                });
            }
        });
        }else{
        $('select[name="state"]').empty();
          }
       });
    });
</script>

Which I specified where to get the data based on country ID and will pass to my routes.php:

url: '/admin/user_register/ajax/'+encodeURI(countryID),

In my routes.php:

    //dynamic dropdown country and states
Route::get('/admin/user_register/ajax/{country_id}',array('as'=>'user_register.ajax','uses'=>'AdminController@stateForCountryAjax'));

Last I added some codes in my AdminController.php what to do:

public function stateForCountryAjax($country_name)
{
    $country_name = urldecode($country_name);
    $country_id = $this->_stateCountryIDForCountryName($country_name);
    $states = DB::table("states")
                ->where("country_id",$country_id)
                ->lists('name','id');
    return json_encode($states);
}

private function _stateCountryIDForCountryName($country_name)
{
    return DB::table('countries')->where("name","$country_name")->first()->country_id;
}

This method works for me. I was able now to dynamically update dropdown option (states) based on Country ID.

like image 30
Kevin Avatar answered Nov 15 '22 16:11

Kevin