Question

I'm fairly new to PHP and MySQL, have a little experience with jQuery and almost no experience with JSON, just to give you some background. I am trying to implement cascading dropdowns in my form.

I have two tables:

|city|
|city_id INT| - PK
|city VARCHAR (45)|
|state_state_id INT | - FK

|state|
|state_id INT| - PK
|state VARCHAR (25)|

Here's my form:

State:<br />
<select name="state" id="stateName">
<?php foreach($rows as $row): ?>
<option value="<?php echo htmlentities($row['state'],ENT_QUOTES,'UTF-8');?>"><?php echo htmlentities($row['state'],ENT_QUOTES,'UTF-8');?>
</option>
<?php endforeach; ?>
</select>
<br /><br />
City:<br />
<select name="city" id="cityName"></select>
<input type="submit" name="work_order_submit" id="" value="Add Work Order" />

I populate the State dropdown with this query:

$query = "SELECT * FROM state WHERE 1 ORDER BY state";
try{
$stmt = $db->prepare($query);
$stmt->execute();
}catch(PDOException $ex){
//On production remove getMessage.
die("Failed to run query: " . $ex->getMessage());
}

$rows = $stmt->fetchAll();

Here's the jQuery I've created to run the JSON and populate the City dropdown with the cascaded values from the state dropdown when a state is selected:

<script>
function populateCityName(){
$.getJSON('state-names.php', {stateName:$('#stateName').val()},
    function(data){
            var select = $('#cityName');
            var options = select.prop('options');
            $('option', select).remove();

            $.each(data, function(index, array){
                     options[options.length] = new Option(array['city']);
                     });

          });
}

$(document).ready(function(){
  populateCityName();
  $('#stateName').on('change', function(){
        populateCityName();
  });
});
</script>

And here's the code in the state-names.php file (I connect to the database before this code):

$rows = array();
if(isset($_GET['stateName'])){
$query = "SELECT city FROM city INNER JOIN state ON city.state_state_id = state.state_id WHERE state = :state ORDER BY city";
$query_params = array(":state" => $_GET['stateName']);
try{
    $stmt = $pdo->prepare($query);
    $stmt->execute($query_params);
}catch(PDOException $ex){
    //On production remove .getMessage.
    die("Failed to run query: " . $ex->getMessage());
}
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
}
echo json_encode($rows);

Nothing happens when I select the state in the form. I don't even get an error. I've tested the SQL and it runs fine and retrieves the values that I want, but for some reason that I can't figure out, the values aren't being cascaded into the City dropdown.

Any help is very much appreciated.

EDIT: As I'm doing more debugging and realizing a few things, this is what I've found so far. The JSON comes in like this:

[{"city":"Salt Lake City"},{"city":"Toole"},{"city":"Provo"},{"city":"St. George"}]

I now know the JSON is working correctly. When I changed the dropdown selection in the state dropdown to a state that I know had entries for the cities, the city dropdown showed blank 'option' fields for the number of entries that there actually were. So, using the answer below and MANY different tutorials on cascading dropdowns and chained dropdowns, I finally figured it out. I've submitted an answer with the working code.

Was it helpful?

Solution

Can you try:

$.each(data, function(index, array){
    // new Option(text [, value, defaultSelected, selected]);
    select.add(new Option(array['city'], index), null);
});

??

OTHER TIPS

All of the code above worked except the jQuery function. Well, the jQuery worked for what I told it to do, not for what I really wanted the code TO DO... Big difference.

Here's the working jQuery that populates the city dropdown based on a selection made in the state dropdown:

<script>
function populateCityName(){
$.getJSON('state-names.php', {stateName: $('#stateName').val()},
    function(data){
        var html = '<option value="';
        var htmlEnd = '</option>';
        var options = '';
        var select = $('#cityName');
        $('option', select).remove();
        $.each(data, function(index, array){
            options += html + array['city'] + '">' + array['city'] + htmlEnd;
         });
        $('#cityName').append(options);
    });
}

$(document).ready(function(){
  populateCityName();
  $('#stateName').on('change', function(){
        populateCityName();
  });
});
</script>

Before, the code would find the number of entries and the select box would show this number, but the selections were blank. With this code, the number of entries is found, but the values for those entries also show. Hope this helps someone else later.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top