0

I'm building a dependent dropdown for country, state and city. It's not going very well. I've done extensive research on the subject on Stackoverflow and other sites on the web for the past few days and have not been able to get the '#state' select object to populate states based on the selected '#country' select object which is populating countries from json just fine. The states are not populating after the country is selected based on the 'change' method. I have an 'if' statement which says, 'if the selected #country === 'US' (which displays as North America), then load the US states and territories .json file.

After fiddling around with the code, I have finally been able to get the '#state' dropdown to at least display 'object [Object]', so I know I'm getting closer to a solution. I'm not quite sure why it's displaying 'object[Object]' in the state dropdown. It may be a 'type' error of some sort where json is being displayed as an object instead of a string as it should but I don't understand how to fix this in the context of my code.

Any help would be greatly appreciated.

Here is the HTML:

<!doctype html>
<html>
<head>
    <title>Country->State->City</title>
</head>
<body>
Country:
<select id="country">
    <pre><option selected value="base">Select Country</option><pre>
</select>

State:
<select id="state">
    <option selected value="base">Select state</option>
</select>

City:
<select id="city">
    <option selected value="base">Select City</option>
</select>

<script type = "text/javascript" src="jquery-2.2.4.min.js"></script>
<script type = "text/javascript" src="custom.js"></script>
</body>
</html>

jQuery

$(function(){
    let countryOptions;
    let stateOptions;
    let gaCitiesOps;

    $.getJSON('countries.json',function(data){
        $.each(data, function(i,country) {
            countryOptions+=
                '<option value= "'+country.code+'">'
                +country.name+
                '</option>';
             });
             $('#country').html(countryOptions);
    });

    $("#country").change(function(){
        if($(this).val()==="US"){
        $.getJSON('us_states.json',function(data){
            $.each(data, function(stateCode,stateName) {
                stateOptions+='<option value="'+stateCode+'">'
                +stateName+
                '</option>';
                 });
                 $('#state').html(stateOptions);
            });
        }
    });

    $("#state").change(function(){
    if($(this).val()==="GA"){
            $.getJSON('GA_cities.json',function(data){
            $.each(data, function(statecode,city) {
                gaCitiesOps +='<option value="'+statecode+'">'
                +city+
                '</option>';
                 });
                 $('#city').html(gaCitiesOps);
            });
        }
    });

});

Countries.json

[
  {
    "code": "US",
    "name": "North America"
  },
  {
    "code": "AG",
    "name": "Antigua"
  },
  {
    "code": "AU",
    "name": "Australia"
  },
  {
    "code": "AT",
    "name": "Austria"
  },
  {
    "code": "BG" ,
    "name": "Bulgaria"
  },
  {
    "code": "CA",
    "name": "Canada"
  },
.....ect

us_states.json

[
  {
    "stateCode": "AL",
    "name": "Alabama"
  },
  {
    "stateCode": "AR",
    "name": "Arkansas"
  },
  {
    "stateCode": "AS",
    "name": "American Samoa"
  },
  {
    "stateCode": "AZ",
    "name": "Arizona"
  },
  {
    "stateCode": "CA",
    "name": "California"
  },
.....etc

GA_cities.json

[
  {
    "code": "ALB",
    "name": "ALBANY"
  },
  {
    "code": "AMR",
    "name": "AMERICUS"
  },
  {
    "code": "ATH",
    "name": "ATHENS"
  },
  {
    "code": "ATL",
    "name": "ATLANTA"
  },
  {
    "code": "AUG",
    "name": "AUGUSTA"
  },
  {
    "code": "BAI",
    "name": "BAINBRIDGE"
  },
....etc

Thanks for your consideration!

brohjoe
  • 854
  • 4
  • 17
  • 39

2 Answers2

2

You're using $.each incorrectly. First argument is the index/key, second is the value. In your case you iterate over array of objects - so first argument is an index and second is each contained object. Use this code for states:

$.each(data, function(index,stateObj) {
            stateOptions+='<option value="'+stateObj.stateCode+'">'
            +stateObj.name+
            '</option>';
             });
             $('#state').html(stateOptions);
        });

And this for cities:

$("#state").change(function(){
    if($(this).val()==="GA"){
            $.getJSON('GA_cities.json',function(data){
            $.each(data, function(index,city) {
                gaCitiesOps +='<option value="'+city.code+'">'
                +city.name+
                '</option>';
                 });
                 $('#city').html(gaCitiesOps);
            });
        }
    });

You can also add options using JS APIs which is slightly better than constructing the entire options HTML as a string and dumping it into html(). See this question for the alternative methods.

Vasan
  • 4,810
  • 4
  • 20
  • 39
  • Thanks guys for your help. I see what you mean about looping through an array and using the correct syntax for accessing json. It works like a charm. Thank you so much!!! – brohjoe May 13 '18 at 03:24
2

console.log() is your best friend. Try logging the values you get from $.each and you will know why you're getting [object Object].

$.each(data, function(stateCode, stateName));

Output is stateCode 0, stateName {stateCode: "AL", name: "Alabama"} $.each arguments are (key, value) and you are looping over an array so key (stateCode in this case) is index of the array.

ES6; If you wanna be fancy you can destructure the arguments to $.each(key, {stateCode, name});

Vasan
  • 4,810
  • 4
  • 20
  • 39
Marwan Fikrat
  • 137
  • 1
  • 8