10

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    |                |
+------------+------------------+------+-----+---------+----------------+
Kevin
  • 315
  • 2
  • 5
  • 19
  • Do you want to update the states when you select a country (to only show the states related to that country)? If yes, you'll need javascript. – tompec Jul 12 '17 at 14:16
  • 1
    This should be done with javascript. Pass the country/state data in as a variable, and change the state with onChange() on the country select. – aynber Jul 12 '17 at 14:16
  • Also, if you're using blade, do not use ` – tompec Jul 12 '17 at 14:17
  • @tompec (to only show the states related to that country) Yes Sir, exactly I would like to make it dynamic dropdown (on change). Can you help me Sir on how will I do the coding? :( Also the proper way to code instead of html tags like: – Kevin Jul 12 '17 at 14:29
  • Yes Sir @aynber, thanks for the response I'm having problem how will I do the coding... :( in laravel – Kevin Jul 12 '17 at 14:31
  • Ok give me a few minutes i'll write you how to do it. – tompec Jul 12 '17 at 14:32
  • I used the bootstrap formhelper for a little while, which has the ability to do what you need. – aynber Jul 12 '17 at 14:33
  • @tompec thank you so much Sir! – Kevin Jul 12 '17 at 14:53

2 Answers2

16

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();
    }
}
tompec
  • 1,220
  • 9
  • 16
  • Please let me know it that works and mark the question as solved if it's the case ;) – tompec Jul 12 '17 at 15:21
  • is there any shorter method in retrieveing data from database and pass in on my dropdowns? like: $countryname = DB::table('countries')->get(); . Then add some js codes for parameter(onchange condition)? – Kevin Jul 13 '17 at 01:07
6

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.

Tiago Martins Peres
  • 14,289
  • 18
  • 86
  • 145
Kevin
  • 315
  • 2
  • 5
  • 19