Home > database >  Issue with JQuery Country and State cascading dropdown showing all states until country dropdown cha
Issue with JQuery Country and State cascading dropdown showing all states until country dropdown cha

Time:01-06

I have cascading dropdowns for country and state in my laravel project. I am using JQuery to refresh the list of available states, depending on the country selected in the country dropdown. This works perfectly.

My issue is when I want to go back and change the state. If i go back to edit the state, because I haven't changed the country dropdown, the state dropdown just lists all states.

I have the states trigered on a change event with the country dropdown box. I am thinking, a quick and dirty method might be to also have the state dropdown refresh on a page load, but i am having issues implementing it.

This is what i have so far,

This is the JQuery in the view

  <script type="text/javascript">
    jQuery(document).ready(function ()
    {
        jQuery('select[name="country"]').on('change',function(){
        var countryID = jQuery(this).val();
        if(countryID)
        {
            jQuery.ajax({
                url : '/getStates/'  countryID,
                type : "GET",
                dataType : "json",
                success:function(data)
                {
                    console.log(data);
                    jQuery('select[name="state"]').empty();
                    jQuery.each(data, function(key,value){
                    $('select[name="state"]').append('<option value="'  key  '">'  value  '</option>');
                    });
                }
            });
        }
        else
        {
            $('select[name="state"]').empty();
        }
    });
});

This is the view dropdown box code showing the country and state dropdowns.

                    <div >
                        <label  for="country">Country</label>
                        <select v-model="form.country"  id="country" name="country">
                            @foreach ($countries as $country)
                                <option value="{{ $country->id }}" {{ $user->country_id == $country->id ? "selected" : "" }}>{{ $country->name }}</option>
                            @endforeach
                        </select>
                    </div>
                    <div >
                        <label  for="state">State</label>
                        <select v-model="form.state"  id="state" name="state">
                            @foreach ($states as $state)
                                <option value="{{ $state->id }}" {{ $user->state_id == $state->id ? "selected" : ""}}>{{ $state->name }}</option>
                            @endforeach
                        </select>
                    </div>

As I said, it works fine, if I first change the country dropdown, the state dropdown will refresh, but if I want to change the state, without changing the country first, then I just get a list of all states. i think if i can trigger the state data refresh on a page load event might fix it, but i can't figure out how to do in JQuery.

CodePudding user response:

Refreshing the country list should be as easy as calling jQuery('select[name="country"]').trigger('change') after setting up the listener, the only caveat is that you'll lose the current state selection, since you'll be emptying and repopulating it. You can get around that by saving its value first and check if it's present in the new state list.

jQuery(document).ready(function ()
    {
        // Cache the jQuery objects, don't look them up in each access
        var $countrySelector = jQuery('select[name="country"]');
        var $stateSelector = jQuery('select[name="state"]');
        
        $countrySelector.on('change',function(){
            var countryID = $countrySelector.val();
            var stateID = $stateSelector.val();
            
            if(countryID)
            {
                jQuery.ajax({
                    url : '/getStates/'  countryID,
                    type : "GET",
                    dataType : "json",
                    success:function(data)
                    {
                        $stateSelector.empty();
                        jQuery.each(data, function(key,value){
                            // Check if current element matches previous selection
                            $stateSelector.append(
                                `<option value="${key}"${key == stateID ? ' selected' : ''}>${value}</option>`
                            );
                        });
                    }
                });
            }
            else
            {
                $stateSelector.empty();
            }
    });
    
    // After document is loaded and handler set up, fire the handler
    $countrySelector.trigger('change');
});

Further reference for template literals.

  •  Tags:  
  • Related