Viewed   103 times

I am trying to create a dynamic set of dropdown boxes, using jQuery/AJAX and PHP/MySQL. The first dropdown box will be populated when the page loads based on values from a database. The second dropdown box should display a set of values based on the selection from the first dropdown box. I know there have been similar questions asked on here before, but I haven't found a solution that matches my scenario.

My query to generate a JSON encoded list of values for the second drop down is functioning, but I am having issues populating it into the actual dropdown form element. Any ideas on where I'm going wrong.

Javascript:

<script>
$().ready(function() {

    $("#item_1").change(function () {   

      var group_id = $(this).val();

       $.ajax({
            type: "POST", 
            url: "../../db/groups.php?item_1_id=" + group_id, 
            dataType: "json",
            success: function(data){
                //Clear options corresponding to earlier option of first dropdown
                $('select#item_2').empty(); 
                $('select#item_2').append('<option value="0">Select Option</option>');
                //Populate options of the second dropdown
                $.each( data.subjects, function(){    
                    $('select#item_2').append('<option value="'+$(this).attr('group_id')+'">'+$(this).attr('name')+'</option>');
                });
                $('select#item_2').focus();
            },
            beforeSend: function(){
                $('select#item_2').empty();
                $('select#item_2').append('<option value="0">Loading...</option>');
            },
            error: function(){
                $('select#item_2').attr('disabled', true);
                $('select#item_2').empty();
                $('select#item_2').append('<option value="0">No Options</option>');
            }
        })  

    }); 
});

</script>

HTML:

<label id="item_1_label" for="item_1" class="label">#1:</label>
<select id="item_1" name="item_1" />
    <option value="">Select</option>
    <?php
        $sth = $dbh->query ("SELECT id, name, level 
                             FROM groups
                             WHERE level = '1'
                             GROUP by name
                             ORDER BY name");                                   
        while ($row = $sth->fetch ()) { 
            echo '<option value="'.$row['id'].'">'.$row['name'].'</option>'."n";       
        }
     ?>
</select>

<label id="item_2_label" for="item_2" class="label">#2:</label>
<select id="item_2" name="item_2" />                        
</select>

PHP:

<?php

require_once('../includes/connect.php');        

$item_1_id = $_GET['item_1_id'];

$dbh = get_org_dbh($org_id);

$return_arr = array();

$sth = $dbh->query ("SELECT id, name, level 
                     FROM groups
                     WHERE level = '2'
                     AND parent = $item_1_id
                     GROUP by name
                     ORDER BY name");   

while ($row = $sth->fetch ()) { 

    $row_array = array("name" => $row['name'], 
                       "id" => $row['id']); 

    array_push($return_arr,$row_array);     
}

echo json_encode($return_arr);

?>  

Sample JSON Output:

[{"name":"A","id":"0"},{"name":"B","id":"1"},{"name":"C","id":"2"}]

 Answers

4

First, your document-ready looks a bit off, it should either be $(document).ready(function(){}); or it could be just $(function(){});.

Second, you looping over the JSON result looks a bit odd as well. Try something like this instead:

$.each(data.subjects, function(i, val){    
   $('select#item_2').append('<option value="' + val.id + '">' + val.name + '</option>');
});
Monday, October 10, 2022
2

Here is what I would do. It isn't glamourous or perfect, but it works amazingly well. You simply set a variable to add the selected attribute to your option tags IF the value coming from the form submit matches. Then output the selected attribute only if that variable matches that option. This can be way harder, but this works and is simple to understand.

Adding a value to the select itself doesn't do anything for you really. It has to be added on the particular option that you want to be auto-selected.

<?php if($orderfield=='ordersessionid'){$session = ' selected="selected"';} ?>
<?php if($orderfield=='ordermoduleid'){$module = ' selected="selected"';} ?>
<?php if($orderfield=='orderteacherid'){$teacher = ' selected="selected"';} ?>
<?php if($orderfield=='orderstudentid'){$student = ' selected="selected"';} ?>
<?php if($orderfield=='ordergrade'){$grade = ' selected="selected"';} ?>

<select name="order">
    <option value="ordersessionid" <?php echo $session; ?>>Session ID</option>
    <option value="ordermoduleid" <?php echo $module; ?>>Module Number</option>
    <option value="orderteacherid" <?php echo $teacher; ?>>Teacher Username</option>
    <option value="orderstudentid" <?php echo $student; ?>>Student Username</option>
    <option value="ordergrade" <?php echo $grade; ?>>Grade</option>
 </select>
Friday, October 21, 2022
 
3
//Index.php
<?php
$conn = mysql_connect("localhost", "root", "root");
$db = mysql_select_db("country_example", $conn);

$sql_country = "SELECT * FROM country";
$result_country = mysql_query($sql_country);

?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Country List</title>
</head>
<body>
<?php 

echo "<select name='country' onChange='get_cities(this.value)'>";

while($row_country = mysql_fetch_array($result_country))
{
    echo "<option value='".$row_country['id']."'>".$row_country['country']."</option>";
}
echo "</select>";
echo "<div id='cityLayer'><select name='city' id='city'></select></div>";
?>
    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
    <script type="text/javascript"> 
    function get_cities($country_id){
     $.ajax({
         url : "city.php?country_id="+$country_id,
         cache : false,
         beforeSend : function (){
              //Show a message
         },
         complete : function($response, $status){
             if ($status != "error" && $status != "timeout") {
                 $('#cityLayer').html($response.responseText);
             }
         },
         error : function ($responseObj){
             alert("Something went wrong while processing your request.nnError => "
                 + $responseObj.responseText);
         }
     }); 
    }
 </script>
</body>
</html>

//City.php
<?php

$conn = mysql_connect("localhost", "root", "root");
$db = mysql_select_db("country_example", $conn);

$country_id = $_REQUEST['country_id'];
$sql_city = "SELECT * FROM cities WHERE country_id = '".$country_id."'";
$result_city = mysql_query($sql_city);

echo "<select name='city'>";
while($row_city = mysql_fetch_array($result_city))
{
    echo "<option value='".$row_city['id']."'>".$row_city['city']."</option>";
}
echo "</select>";
?>
Wednesday, November 30, 2022
 
bkr
 
bkr
4

As some of the comments pointed out, listen to the change of you first select element to dynamically generate the options for you second select with a filter.

Something like:

filterSubById(id) {
    return this.subCategories.filter(item => item.parentId === id);
}

I've made a quick working demo to show how.

EDIT

The way this works is that the selected value from the first select is bound to the mainCategory property of your component. Hence, mainCategory changes depending on what the user selects from the first menu. The second select dynamically loads the options depending on what the user chooses on the first one; this is accomplished with a filter function that returns all the elements in the subCategories array whose parentId matches the id of the option selected in the first menu.

Thursday, December 15, 2022
4

You're using the node variable in the second ngFor outside of its scope. This variable only exists inside the element(and its attributes) that the ngFor is acting on.

What you probably want to do is wait for changes to the selected value of the first select, update some variable in your controller, which should then cause the second ngFor to update. This can be done by using ngModelChange:

<div class="row">
<div class="col-md-12">
    <label>Choose a room</label>
    <select [(ngModel)]="nodes" (ngModelChange)="selectedNode=$event.target.value">
        <option *ngFor="let node of nodes"[ngValue]="node">{{node.name}}</option>
    </select>

    <br/><br/>
    <label>Choose an item</label>
    <div *ngFor="let module of selectedNode.modules">
        <select [(ngModel)]="channels">
            <option *ngFor="let channel of module.channels">
              {{channel.name}}
             </option>
        </select>
    </div>
</div>
Saturday, November 5, 2022
Only authorized users can answer the search term. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :