Когда я добавляю div один за другим, он работает правильно. но когда я удаляю первый или любой из предыдущих, он не удаляется должным образом. И если я снова хочу добавить еще один div-номер ...

0
Md. Ashiqur Rahaman Dipto 3 Янв 2021 в 11:24

1 ответ

Лучший ответ

В этом коде есть много важных проблем.

  1. Вы создаете несколько динамических элементов, имеющих всегда один и тот же id.
    id должен быть уникальным. НИКОГДА не используйте идентификатор в цикле или в обработчике событий, который добавляет элементы.
    Вместо этого используйте class.

  2. Если у вас есть более одной или двух строк HTML, объединенных в строку для некоторого добавления ... Лучше использовать . clone () в «шаблоне», скрытом в HTML.
    Это делает ваш код более читаемым и поддерживаемым, поскольку «шаблон» для клонирования будет отображаться в вашем редакторе кода как обычный HTML, поэтому вы можете сразу увидеть опечатки. И тогда JS более лаконичен.

  3. Основным преимуществом использования jQuery является простота «обхода» DOM с помощью простых и коротких методов.
    Из действия пользователя (например, из события, инициированного элементом <select>) ... Используйте широкий набор методов, например . parent (), .closest (), . find () , . siblings () и т. д. для нацеливания на нужные элементы.

    Напоминание для вашего будущего кодирования : каждый раз, когда вам нужно добавить число к классу, чтобы сделать его уникальным ... Воспринимайте это как симптом плохого кодирования. В то время как id должен быть уникальным для ОДНОГО элемента, класс должен быть «универсальным» для нацеливания на набор похожих элементов.

    Я ПОЛНОСТЬЮ удалил вашу "концепцию" наличия divCount переменной div_title в приведенном ниже фрагменте. Ваша проблема заключалась НЕ в том, как правильно его использовать ... Но как НЕ использовать. ;)

  4. Вложенность функций.
    Вы использовали делегирование событий: $(document).on("change", ".product_option", function () {...}
    Хорошо! Но это внутри обратного вызова Firebase. И запрос Firebase находится внутри обработчика кликов btnAddtoList.

    Таким образом, каждый раз, когда пользователь нажимает кнопку পণ্য যোগ করুন (Add products), к базе данных делается запрос (скорее всего, с тем же результатом). И дополнительный делегированный обработчик для всего .product_option выбора на странице устанавливается.

    Выглядит не очень хорошо, правда?
    И это из-за вашей (неудачной) попытки использовать некоторые "уникальные" классы item-wrapper-* ...



Итак, ниже ваш код сильно изменился. Я не углублялся в ваш запрос Firebase, потому что я действительно не знаю структуру ответа. Я "предположил" ответ с массивом объектов snapshot. У вас может быть что-то совсем другое.

Внимательно изучите код и все комментарии.

console.clear();

$(function () {
  
  // Add a cloned div
  $("#btnAddtoList").on("click", function () {
    
    // Clone the template and toggle some classes
    let newDiv = $(".item-wrapper_template")
      .clone()
      .toggleClass("item-wrapper_template item-wrapper");
    
    // Append
    newDiv.find(".number").text($(".item-wrapper").length + 1);
    $(".productDiv").append(newDiv);
    
    // Instantiate Select2
    newDiv.find(".product_option").select2({
      theme: "classic"
    });
  });

  // Delete a cloned div
  $(document).on("click", ".deleteItem", function () {
    
    // Remove the whole wrapper div that holds the .deleteItem button
    $(this).closest(".item-wrapper").remove();
    
    // Update the numbers of the other items
    $(".item-wrapper").each(function (num) {
      $(this)
        .find(".number")
        .text(num + 1);
    });
  });

  // Calculate the sub total
  $("#subTotal").on("click", function (e) {
    
    // At each click event, start the calculation at zero
    let subTotalAmount = 0;
    
    // How many items now?
    let itemCount = $(".item-wrapper").length;

    // A flag to know if we break the loop
    let loopBreak = false;

    // Looping all the items
    for (let i = 0; i < itemCount; i++) {
      
      let getSellingPrice = parseFloat(
        $(".item-wrapper").eq(i).find(".sellPrice").val()
      );
      let getAmount = parseFloat(
        $(".item-wrapper").eq(i).find(".amount").val()
      );
      let getQuantity =
        parseFloat($(".item-wrapper").eq(i).find(".quantity").val()) || 0;

      // A condition check which may break the loop
      if (getQuantity > getAmount) {
        alert("পর্যাপ্ত পরিমান পণ্য নেই ।"); // There are not enough products.
        loopBreak = true;
        break;
      } else {
        subTotalAmount += getSellingPrice * getQuantity;
        console.log("subTotalAmount", subTotalAmount);
      }
    } // END for loop

    // If the loop was not broken
    if (!loopBreak) {
      $(".subTotalDiv").find(".subTotalAmount").text(subTotalAmount);
      $(".subTotalDiv").show();
    }
  });

  // Option change handler for ALL select element present on the page
  $(document).on("change", ".product_option", function () {
    const valArr = $(this).find("option:selected").text().split(" | ");
    $(this).closest(".item-wrapper").find(".productName").val(valArr[0]);
    $(this).closest(".item-wrapper").find(".sellPrice").val(valArr[1]);
    $(this).closest(".item-wrapper").find(".amount").val(valArr[2]);
  });
  
  
  // =====
  // Simulating the firebase database request

  // Let assume some data to make this example working
  let snapshot = [
    {
      product_name: "First Product",
      selling_price: 10.57,
      product_quantity: 42
    },
    {
      product_name: "Second Product",
      selling_price: 28.72,
      product_quantity: 17
    },
    {
      product_name: "Third Product",
      selling_price: 11.48,
      product_quantity: 8
    }
  ];

  /*
    firebase.auth().onAuthStateChanged(function(user) {
      console.log(user);
      if (user) {
        var user_id = user.uid;

        firebase.database().ref('Products/').child(user_id).once('value')
        .then(function(snapshot){
        
          snapshot.forEach(function(childSnapshot) {
            var product_name = childSnapshot.child("product_name").val();
            var selling_price = childSnapshot.child("selling_price").val();
            var amount = childSnapshot.child("product_quantity").val();
            
            {#console.log(amount)#}
            var total = product_name + " | " + selling_price + " | " + amount;
            console.log(total);
            
            $(".item-wrapper-" + div_title).find(".product_option").append('<option>'
            + total + '</option');

          });
          */
  
          // Here, I am simulating the option appending from the simulated snapshot array above
          // Notice I append it to the template!
          snapshot.forEach(function (item, index) {
            
            // Format the text of the option
            let optionText =
              item.product_name +
              " | " +
              item.selling_price +
              " | " +
              item.product_quantity;
            
            // Create the option and append
            let option = $("<option>").text(optionText);
            $(".item-wrapper_template").find(".product_option").append(option);
          });
  
          /*
        })
      }
      else{
        window.location.href="{% url 'login' %}";
      }
    });
    */
});
.item-wrapper_template{
  display: none;
}
.subTotalDiv{
  display: none;
}
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet"/>
<link href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.13/css/select2.min.css" rel="stylesheet"/>

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.bundle.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.13/js/select2.min.js"></script>

<div class="productDiv"></div>

<!-- That is a TEMPLATE -->
<div class=item-wrapper_template>
  <div class="container rounded bg-white mt-3 mb-3">
    <div class="row">
      <div class="col-md-12">
        <div class="row mt-3">
          <span><strong>পণ্যের বিবরণ (Product Description) #</strong></span><span class="number">0</span>
        </div>
        <div class="row mt-1 text-center">
          <select class="product_option form-control">
            <option disabled selected> -- পণ্য পছন্দ করুন (পণ্যের নাম | বিক্রয় মূল্য | অ্যাভেলেবল আছে) -- </option>
            <option disabled> -- Choose Product (Product Name | Sale Price | Available) -- </option>
          </select>
        </div>
        <div class="row mt-3">
          <label class="labels" style="font-size: 16px">পণ্যের নাম (Product name)</label> <input type="text" class="form-control productName">
        </div>
        <div class="row mt-3">
          <label class="labels" style="font-size: 16px">বিক্রয় মূল্য (Sale price)</label> <input type="number" class="form-control sellPrice">
        </div>
        <div class="row mt-3">
          <label class="labels" style="font-size: 16px">পণ্য মজুদ আছে (There are stockpiles of products)</label> <input type="text" class="form-control amount">
        </div>
        <div class="row mt-3">
          <label class="labels" style="font-size: 16px">পরিমাণ (Amount)</label> <input type="number" class="form-control quantity_pro quantity">
        </div>
        <div class="mt-3 d-flex flex-column align-items-center text-center"> <button class="btn btn-danger deleteItem" type="button">মুছুন (Delete)</button> </div>
      </div>
    </div>
  </div>
</div>

<!-- That is your "normal" HTML -->
<div class="mt-3 text-center">
  <button id="btnAddtoList" class="btn profile-button" type="button">পণ্য যোগ করুন (Add products)</button>
</div>
<div class="mt-3 text-center">
  <button id="subTotal" class="btn profile-button" type="button">সাব টোটাল (Sub Total)</button>
</div>

<!-- That is hidden by CSS but shown by JS -->
<div class="subTotalDiv">
  <div class="container rounded bg-white mt-3 mb-3">
    <div class="row">
      <div class="col-md-12">
        <div class="row mt-3">
          <span class="col-md-12">সাব টোটালঃ (Sub Total:)</strong></span><span class="subTotalAmount">0</span>
        </div>
        <div class="row mt-3">
          <label class="labels" style="font-size: 16px">ডিসকাউন্ট(%) (Discount (%))</label><input type="text" class="form-control">
        </div>
        <div class="row mt-3">
          <label class="labels" style="font-size: 16px">ভ্যাট(%) (VAT (%))</label><input type="text" class="form-control sellPrice">
        </div>
        <div class="row mt-3">
          <span class="col-md-12"><strong>মোটঃ (Total:)</strong></span>
        </div>
        <div class="mt-3 d-flex flex-column align-items-center text- center"> <button class="btn btn-info" type="button">মোট (Total)</button></div>
      </div>
    </div>
  </div>
</div>

CodePen

1
Louys Patrice Bessette 3 Янв 2021 в 19:24