Skip to content

Dynamic dropdown selection for dynamic rows not just first row

I have created a form for entering product data which sends the results back to the mysql database. I have a dropdown/select id named ‘attribute_name’ and the other ‘attribute_value’ I have managed to send the results back to the database and that is working great. I would however like to restrict the user to only choosing values based on the name so if they selected size they would only have the values of small, medium, large and not black, camo, purple from colour and vice versa.

The script at the bottom works on the first row but not on any other rows as shown in the screenshots.

Working

enter image description here

Not working

enter image description here

Code

    <?php
    include 'assets/processes/db-connection.php';
    $query = "SELECT * 
                FROM attribute_name;";
    $query_run = mysqli_query($conn, $query);
    $att_name = "<select name='attribute_name' id='attribute_name' class='form-control country'>";
    $att_name .= "<option value='0'></option>";
    while ($row = mysqli_fetch_assoc($query_run)) {
    $att_name .= "<option value='{$row['attribute_name']}'>{$row['attribute_name']}</option>";
    }
    $att_name .= "</select>"
    ?>
      <?php
    include 'assets/processes/db-connection.php';
    $query = "SELECT `attribute`.*, `attribute_name`.*
                FROM `attribute` 
                    LEFT JOIN `attribute_name` ON `attribute`.`attribute_name_id` = `attribute_name`.`attribute_name_id`;";
    $query_run = mysqli_query($conn, $query);
    $att_value = "<select name='attribute_id' id='attribute_value' class='form-control'>";
    $att_value .= "<option value='0'></option>";
    while ($row = mysqli_fetch_assoc($query_run)) {
    $att_value .= "<option data-parent='{$row['attribute_name']}' value='{$row['attribute_id']}'>{$row['attribute_value']}</option>";
    }
    $att_value .= "</select>"
    ?>

        <div id="wrapper">
          <div id="form_div">
            <table class="table table-hover text-nowrap" id="attribute_table">
              <thead>
                <tr>
                  <th>Name</th>
                  <th>Value</th>
                  <th colspan="1">Action</th>
                </tr>
              </thead>
              <tr id="row1">
                <td>
                  <?php echo $att_name; ?>
                </td>
                <td>
                  <?php echo $att_value; ?>
                </td>
                <td><input class="btn btn-block btn-primary" type="button" onclick="add_attribute_row();" value="+"></td>
              </tr>
            </table>
          </div>
        </div>
        <script>
          $('#attribute_name').change(function() { var parent = $(this).val(); $('#attribute_value').children().each(function() { if ($(this).data('parent') != parent) { $(this).hide(); } else $(this).show(); }); });
          </script>

This code is edited for use on stackoverflow

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<div id="wrapper">
    <div id="form_div">
        <table class="table table-hover text-nowrap" id="attribute_table">
            <thead>
                <tr>
                    <th>Name</th>
                    <th>Value</th>
                    <th colspan="1">Action</th>
                </tr>
            </thead>
            <tr id="row1">
                <td>
                    <select name='attribute_name' id='attribute_name' class='form-control'>
                    <option value='0'></option>
                    <option value='Colour'>Colour</option>
                    <option value='Size'>Size</option>
                    </select>
                </td>
                <td>
                    <select name='attribute_id' id='attribute_value' class='form-control'>
                    <option value='0'></option>
                    <option data-parent='Colour' value='1'>Black</option>
                    <option data-parent='Colour' value='2'>Camo</option>
                    <option data-parent='Colour' value='3'>Purple</option>
                    <option data-parent='Size' value='4'>Small</option>
                    <option data-parent='Size' value='5'>Medium</option>
                    <option data-parent='Size' value='6'>Large</option>
                    </select>
                </td>
                <td><input class="btn btn-block btn-primary" type="button" onclick="add_attribute_row();" value="+"></td>
            </tr>
        </table>
    </div>
</div>
<script>
function add_attribute_row() {
    $rowno = $("#attribute_table tr").length;
    $rowno = $rowno + 1;
    $("#attribute_table tr:last").after("<tr id='row" + $rowno + "'><td><select name='attribute_name' id='attribute_name' class='form-control'><option value='0'></option><option value='Colour'>Colour</option><option value='Size'>Size</option></select></td><td><select name='attribute_id' id='attribute_value' class='form-control'><option value='0'></option><option data-parent='Colour' value='1'>Black</option><option data-parent='Colour' value='2'>Camo</option><option data-parent='Colour' value='3'>Purple</option><option data-parent='Size' value='4'>Small</option><option data-parent='Size' value='5'>Medium</option><option data-parent='Size' value='6'>Large</option></select></td><td><input class='btn btn-block btn-primary' type='button' value='-' onclick=del_att_row('row" + $rowno + "')></td></tr>");
}
function del_att_row(rowno) {
    $('#' + rowno).remove();
};
</script>
<script>
    $('#attribute_name').bind('change', function () {
        var parent = $(this).val();
        $('#attribute_value').children().each(function () {
            if ($(this).data('parent') != parent) {
                $(this).hide();
            } else
                $(this).show();
        });
    });
</script>

Answer

  1. First of all, you are not allowed to use duplicate ID. You should use class instead. Check this answer Class vs ID.

  2. Secondly, I’ve changed your change event with .on('change') which will work for dynamically added select. Check this sample JQuery .on(‘change’).

  3. Lastly, you don’t want to select all select with class attribute-name, you need to find the select on that particular row. You can do this by using .closest(‘tr’) selector to select the current row <tr> where the event happened, and then use **.find('.attribute-value')** which will traverse and find element with the class attribute-value`.

From the documentation:

  • The .closest selector traverses up the DOM to find the parent that matches the conditions.
  • The .find selector traverses down the DOM where the event occurred, that matches the conditions.

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<div id="wrapper">
    <div id="form_div">
        <table class="table table-hover text-nowrap" id="attribute_table">
            <thead>
                <tr>
                    <th>Name</th>
                    <th>Value</th>
                    <th colspan="1">Action</th>
                </tr>
            </thead>
            <tr id="row1">
                <td>
                    <select name='attribute_name' id='attribute_name' class='form-control attribute_name'>
                    <option value='0'></option>
                    <option value='Colour'>Colour</option>
                    <option value='Size'>Size</option>
                    </select>
                </td>
                <td>
                    <select name='attribute_id' id='attribute_value' class='form-control attribute_value'>
                    <option data-parent='0' value='0'></option>
                    <option data-parent='Colour' value='1'>Black</option>
                    <option data-parent='Colour' value='2'>Camo</option>
                    <option data-parent='Colour' value='3'>Purple</option>
                    <option data-parent='Size' value='4'>Small</option>
                    <option data-parent='Size' value='5'>Medium</option>
                    <option data-parent='Size' value='6'>Large</option>
                    </select>
                </td>
                <td><input class="btn btn-block btn-primary" type="button" onclick="add_attribute_row();" value="+"></td>
            </tr>
        </table>
    </div>
</div>
<script>
function add_attribute_row() {
    $rowno = $("#attribute_table tr").length;
    $("#attribute_table tr:last").after("<tr id='row" + $rowno + "'><td><select name='attribute_name' id='attribute_name' class='form-control attribute_name'><option value='0'></option><option value='Colour'>Colour</option><option value='Size'>Size</option></select></td><td><select name='attribute_id' id='attribute_value' class='form-control attribute_value'><option data-parent='0' value='0'></option><option data-parent='Colour' value='1'>Black</option><option data-parent='Colour' value='2'>Camo</option><option data-parent='Colour' value='3'>Purple</option><option data-parent='Size' value='4'>Small</option><option data-parent='Size' value='5'>Medium</option><option data-parent='Size' value='6'>Large</option></select></td><td><input class='btn btn-block btn-primary' type='button' value='-' onclick=del_att_row('row" + $rowno + "')></td></tr>");
}
function del_att_row(rowno) {
    $('#' + rowno).remove();
};
</script>
<script>
$(document).on('change', '.attribute_name', function () {
        var parent = $(this).val();  $(this).closest('tr').find('.attribute_value').children().each(function () {
            if ($(this).data('parent') != parent) {
                $(this).hide();
            } else
                $(this).show();
        });
    });
</script>