select option created with var not displaying when adding a new field dynamically

Tags: , , ,



I have a little problem here, when i add a new field the select option i created from var won’t show. I have tried a multiple method like changing from id into class, add a var option name into <select> in var html and it still doesn’t work. I suppose my JS nesting is the problem or something missing? If so any suggestion what code i must change or add here?

var data = {
            Food: [
                {
                    id: 1,
                    name: 'Fried Rice',
                    price: 10000
                },
                {
                    id: 2,
                    name: 'Fried Noodle',
                    price: 9000
                },
                {
                    id: 3,
                    name: 'Pancake',
                    price: 8500
                },
                {
                    id: 4,
                    name: 'French Fries',
                    price: 7500
                }
            ],
            Drink: [
                {
                    id: 1,
                    name: 'Cola',
                    price: 4600
                },
                {
                    id: 2,
                    name: 'Orange Juice',
                    price: 5400
                },
                {
                    id: 3,
                    name: 'Mineral Water',
                    price: 3500
                },
                {
                    id: 4,
                    name: 'Coffee',
                    price: 5800
                }
            ]
        }

        function handleChange() {
            var x = document.getElementById("category_select").value;

            var dataOptions = data[x]
            var dataSelect = document.getElementById('type_select')
            dataSelect.innerHTML = ''

            dataOptions.forEach(function (option) {
                var optionEle = document.createElement('option')
                optionEle.value = option.id
                optionEle.label = option.name
                optionEle.setAttribute('data-price', option.price)

                dataSelect.appendChild(optionEle)
            })

        }
        handleChange()

        $(".addRow").click(function () {
            var html = '';
            html += '<div class="row">';
            html += '<div class="col-md-3">';
            html += '<button type="button" class="btn btn-danger btn-lg delRow">Del</button>';
            html += '</div>';
            html += '<div class="col-md-3">';
            html += '<select class="form-select form-select-lg mb-3" id="category_select" onChange="handleChange()">';
            html += '<option value="Food">Food</option>';
            html += '<option value="Drink">Drink</option>';
            html += '</select>';
            html += '</div>';
            html += '<br>';
            html += '<div class="col-md-3">';
            html += '<select class="form-select form-select-lg mb-3" id="type_select">' + $("#type_select option:selected").attr('label') + '</select>'; //select option from var data didn't show here
            html += '</div>';
            html += '<div class="col-md-3">';
            html += '<input type="number" class="form-control form-control-lg mb-3" id="num" placeholder="Qty" min="0">';
            html += '</div>';
            html += '</div>';

            $('.container-fluid').append(html);
        });

        $(document).on('click', '.delRow', function () {
            $(this).closest('.row').remove();
        });

        $(document).ready(function () {
            var selectMenu = {};
            $(".order").click(function () {
                var itemName = $("#type_select option:selected").attr('label');
                var price = Number($("#type_select option:selected").data('price'));
                var count = Number($("#num").val());
                var total = price * count;
                selectMenu[itemName] = total
                var result = JSON.stringify(selectMenu).replace(/,/g, '<br>').replace(/{|}|"/g, "")

                $(".result").html(result);
            });

        });
button[type=submit] {
            width: 50%;
            margin-left: 25%;
            margin-right: 25%;
        }

        button[type=button] {
            font-size: 20px;
            width: 50%;
            margin-left: 25%;
            margin-right: 25%;
        }
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/css/bootstrap.min.css" rel="stylesheet"
        integrity="sha384-giJF6kkoqNQ00vy+HMDP7azOuL0xtbfIcaT9wjKHr8RbDVddVHyTfAAsrekwKmP1" crossorigin="anonymous">
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
    
    <div class="container">
        <div class="container-fluid text-center">
            <h2 style="font-size:70px; font-family:Lucida Console;">MENU</h2>
            <br>
            <div class="row">
                <div class="col-md-3">
                    <button type="button" class="btn btn-primary btn-lg addRow">Add</button>
                </div>
                <div class="col-md-3">
                    <select class="form-select form-select-lg mb-3" id="category_select" onChange='handleChange()'>
                        <option value="Food">Food</option>
                        <option value="Drink">Drink</option>
                    </select>
                </div>
                <br>
                <div class="col-md-3">
                    <select class="form-select form-select-lg mb-3" id="type_select"></select>
                </div>
                <div class="col-md-3">
                    <input type="number" class="form-control form-control-lg mb-3" id="num" placeholder="Qty" min="0">
                </div>
            </div>
        </div>
    </div>
    <br>
    <button type="submit" class="btn btn-secondary order">Order</button>
    <br>
    <br>
    <div class="result text-center"></div>

Feel free to add some code or change the code as your preferences

Answer

You can pass this inside your handleChange function where this refer to current select-box which is change then using that get other select-box reference and change values .

Demo Code :

var data = {
  Food: [{
      id: 1,
      name: 'Fried Rice',
      price: 10000
    },
    {
      id: 2,
      name: 'Fried Noodle',
      price: 9000
    },
    {
      id: 3,
      name: 'Pancake',
      price: 8500
    },
    {
      id: 4,
      name: 'French Fries',
      price: 7500
    }
  ],
  Drink: [{
      id: 1,
      name: 'Cola',
      price: 4600
    },
    {
      id: 2,
      name: 'Orange Juice',
      price: 5400
    },
    {
      id: 3,
      name: 'Mineral Water',
      price: 3500
    },
    {
      id: 4,
      name: 'Coffee',
      price: 5800
    }
  ]
}

function handleChange(el) {
  //if undefined use closest & find to get select value
  var els_cat = (el != undefined) ? $(el).closest(".outer").find(".cat").val() : $("#category_select").val()
  console.log(els_cat)
  var els_type = (el != undefined) ? $(el).closest(".outer").find(".type") : $("#type_select")
  var dataOptions = data[els_cat]
  els_type.html('') //empty
  dataOptions.forEach(function(option) {
    var optionEle = document.createElement('option')
    optionEle.value = option.id
    optionEle.label = option.name
    optionEle.setAttribute('data-price', option.price)
    els_type.append(optionEle) //append same
  })
}
handleChange()

$(".addRow").click(function() {
  var cloned = $("#type_select").clone() //cloned select
  var html = '';
  //added one outer class
  html += '<div class="row outer">';
  html += '<div class="col-md-3">';
  html += '<button type="button" class="btn btn-danger btn-lg delRow">Del</button>';
  html += '</div>';
  html += '<div class="col-md-3">';
  html += '<select class="form-select form-select-lg mb-3 cat" onChange="handleChange(this)">'; //use clone for this as well if needed same options ..
  html += '<option value="Food">Food</option>';
  html += '<option value="Drink">Drink</option>';
  html += '</select>';
  html += '</div>';
  html += '<br>';
  html += '<div class="col-md-3">';
  html += '<select class="form-select form-select-lg mb-3 type">' + $(cloned).html() + '</select>'; //pass same
  html += '</div>';
  html += '<div class="col-md-3">';
  html += '<input type="number" class="form-control form-control-lg mb-3" id="num" placeholder="Qty" min="0">';
  html += '</div>';
  html += '</div>';

  $('.container-fluid').append(html);
});
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-giJF6kkoqNQ00vy+HMDP7azOuL0xtbfIcaT9wjKHr8RbDVddVHyTfAAsrekwKmP1" crossorigin="anonymous">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>

<div class="container">
  <div class="container-fluid text-center">
    <h2 style="font-size:70px; font-family:Lucida Console;">MENU</h2>
    <br>
    <!--added classs-->
    <div class="row outer">
      <div class="col-md-3">
        <button type="button" class="btn btn-primary btn-lg addRow">Add</button>
      </div>
      <div class="col-md-3">
        <!--added class cat -->
        <select class=" form-select form-select-lg mb-3 cat" id="category_select" onChange='handleChange(this)'>
          <option value="Food">Food</option>
          <option value="Drink">Drink</option>
        </select>
      </div>
      <br>
      <div class="col-md-3">
        <!--added class cat -->
        <select class="form-select form-select-lg mb-3 type" id="type_select"></select>
      </div>
      <div class="col-md-3">
        <input type="number" class="form-control form-control-lg mb-3" id="num" placeholder="Qty" min="0">
      </div>
    </div>
  </div>
</div>
<br>
<button type="submit" class="btn btn-secondary order">Order</button>
<br>
<br>
<div class="result text-center"></div>


Source: stackoverflow