Search code examples
javascriptjqueryhtmljsonchained-select

jQuery and JSON: chained select from an array with multiple values


I have a JSON file (json/cities.json) which associates the states of my country to its cities in the following form:

{
    "State #1": [
        "City #1 from State #1",
        "City #2 from State #1",
        "City #3 from State #1"
    ],
    "State #2": [
        "City #1 from State #2",
        "City #2 from State #2",
        "City #3 from State #2"
    ]
}

I also have a HTML select with the states, like this:

<select id="state" name="state">
    <option value="State #1"> State #1 </option>
    <option value="State #2"> State #2 </option>
</select>

and an empty HTML select for the cities:

<select id="city" name="city"></select>

What I am trying to do is to fill the HTML select of the cities with the JSON values filtered by the key (state).

I am using the following jQuery script:

$('#state').on('change', function () {
    var state = $(this).val(), city = $('#city');
    $.getJSON('json/cities.json', function (result) {
        $.each(result, function (i, value) {
            if (i === state) {
                 var obj = city.append($("<option></option>").attr("value", value).text(value));
                 console.log(obj);
            }
        });
    });
});

The problem is that the select that should be filled with the cities doesn't even change while console.log returns the following markup:

<select name="city" id="city">
    <option value="City #1 form State #1, City #2 from State #1, City #3 from State #1">
        City #1 from State #1, City #2 from State #1, City #3 from State #1
    </option>
</select>

That is, the values are returned as one value where it should be multiple values (each one separated by comma).


Solution

  • My proposal:

    $('#state').on('change', function () {
      var state = $(this).val(), city = $('#city');
      $.getJSON('json/cities.json', function (result) {
        var values = result[state];
        if (values != undefined && values.length > 0) {
          city.find('option').remove();
          $(values).each(function(index, element) {
            city.append($("<option></option>").attr("value", element).text(element));
          });
        }
      });
    });