Home > Mobile >  How to use jQuery foreach in a shopping cart quantity add/remove function
How to use jQuery foreach in a shopping cart quantity add/remove function

Time:12-13

Here is the code I want to use to allow user control the product quantity in a shopping cart. The problem is, if there are 2 product or more in the same cart, if I try to increase one product quantity, it will increase all products quantity. I would like to use the foreach function in the jQuery code , I tried to insert PHP $i , but it didn't work. can someone help please ? I just want separate product quantity increase/decrease for each product (form)

<?php
if (isset($_POST['submit'])) {
$product_quantity= $_POST['quantity'];
} else {$product_quantity= "1";}
?>

<form  method='POST' action=''>
<input type = "submit" value="-" name = "submit" value = "Submit"  field="quantity" >
<input type='text' name='quantity' value='<?php echo $product_quantity; ?>' class='qty form-control' />
<input type = "submit" value=' ' name = "submit" value = "Submit" class='qtyplus btn btn-success btn-sm' field='quantity' >
</form>
<form  method='POST' action=''>
<input type = "submit" value="-" name = "submit" value = "Submit"  field="quantity" >
<input type='text' name='quantity' value='<?php echo $product_quantity; ?>' class='qty form-control' />
<input type = "submit" value=' ' name = "submit" value = "Submit" class='qtyplus btn btn-success btn-sm' field='quantity' >
</form>


<script src="jquery/jquery.min.js"></script>
<script>
    jQuery(document).ready(function() {
    $('.qtyplus').click(function(e) {
        fieldName = $(this).attr('field');
        var currentVal = parseInt($('input[name='   fieldName   ']').val());
        if (!isNaN(currentVal)) {
            $('input[name='   fieldName   ']').val(currentVal   1);
        } else {
            $('input[name='   fieldName   ']').val(1);
        }
    });
    $(".qtyminus").click(function(e) {
        fieldName = $(this).attr('field');
        var currentVal = parseInt($('input[name='   fieldName   ']').val());
        if (!isNaN(currentVal) && currentVal > 1) {
            $('input[name='   fieldName   ']').val(currentVal - 1);
        } else {
            $('input[name='   fieldName   ']').val(1);
        }
    });
});
</script>

CodePudding user response:

In your click event handler you were fetching the input element using a selector in the whole document that was going to return multiple elements.

Instead you should rely on the element triggering the event and query its subtree to address the specific input element for which you intended to increment or decrement the value.

So in your click event handler,$(this) will be the button triggering the event, and from there you can select its parent form by doing $parent = $(this).closest('form') and query its children without involving the whole document by doing $parent.find(/*selector*/) instead of $(/*selector*/)

Here in this example I also made the function addToInput that will handle the logics in general dealing with the clicked $button and the amount to add passed as arguments.

Plus since you were using input type="submit" for your plus and minus buttons, I changed them to type="button" so that the form won't be sumitted at each click. Of course if that was your intended behaviour just revert back to original. But yet those two buttons, for each row, were having the same value for the name attribute and since they belong to the same form, it would be more appropriate to have each one its own name.

[EDIT after @Roko's comment]

As a final note, you were using the attribute field in your plus and minus buttons to know the name of the input element that they had to address. Now left aside the fact that, as is, in this exact code, it's not needed because there's no ambiguity since it's the only input type=text and that condition would be enough to fetch it with no added condition. But yet if you wanted to use such a strategy it was more appropriate to use a data attribute instead:

https://developer.mozilla.org/en-US/docs/Learn/HTML/Howto/Use_data_attributes

Since field is not a valid attribute for that element as for HTML5 specs.

$(document).ready(function() {

  const addToInput = ($button, amount) => {    
    const $parent = $button.closest('form');
    //const fieldName =  $button.attr('field');
    const fieldName =  $button.data('field');
    const $input = $parent.find(`input[name=${fieldName}]`);
    const currentVal = parseInt($input.val());    
    if (!isNaN(currentVal)) {
      $input.val(currentVal   amount);
    } else {
      $input.val(1);
    }
  }

  $('.qtyplus').click(function(e) {    
    addToInput($(this),  1);
  });
  
  $(".qtyminus").click(function(e) {
    addToInput($(this), -1);
  });
  
});
input[type="button"]{
  cursor: pointer;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

  <form  method='POST' action=''>
    <input
      type="button"
      value="-"
      name="minus"      
      
      data-field="quantity">
    <input type='text' name='quantity' value='1' class='qty form-control' />
    <input
      type="button"
      value=' '
      name="plus"      
      class='qtyplus btn btn-success btn-sm'
      data-field='quantity'>
  </form>
  
  <form  method='POST' action=''>
      <input
      type="button"
      value="-"
      name="minus"      
      
      data-field="quantity">
    <input type='text' name='quantity' value='1' class='qty form-control' />
    <input
      type="button"
      value=' '
      name="plus"      
      class='qtyplus btn btn-success btn-sm'
      data-field='quantity'>
  </form>

CodePudding user response:

  • Use Event delegation using the jQuery's .on() method:
    $(".staticParent").on("eventName", ".dynamicChild", fn)
    Then refer to the Event delegator parent using $(evt.delegateTarget) and to the currently clicked button using $(evt.currentTarget) (is you use Arrow Function (evt) => {) , or by using $(this) if you use Regular Function function(evt) {
  • Fix the issues in your HTML markup such as attributes (names, duplicated value, etc). Don't use invalid non-HTML5 attributes. Use data-* attributes if really needed. (Not needed for this code to work)
  • Prevent your value go negative using Math.max()

jQuery($ => { // DOM ready and $ alias in scope
  
  $(".cart-items-number").on("click", ".qtyminus, .qtyplus", (evt) => {
    const $qty    = $(evt.delegateTarget).find(".qty");
    const isMinus = $(evt.currentTarget).hasClass("qtyminus");
    const valueCurrent =  $qty.val() || 0;
    const valueChange = isMinus ? -1 : 1;
    const value = Math.max(0, valueCurrent   valueChange);
    $qty.val(value);
  });
  
});
.cart-items-number { display: inline-flex; }
<link
  href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css"
  rel="stylesheet"
  type="text/css" />


<form  method='POST' action=''>
  <button type="button" >-</button>
  <input type='text' name='quantity' value='0' class='qty form-control' />
  <button type="button" class='qtyplus btn btn-success btn-sm'> </button>
</form>
  
<form  method='POST' action=''>
  <button type="button" >-</button>
  <input type='text' name='quantity' value='5' class='qty form-control' />
  <button type="button" class='qtyplus btn btn-success btn-sm'> </button>
</form>


<script src="//code.jquery.com/jquery.min.js"></script>

  • Alternatively, you could use the input[type=number] instead, and its native JavaScript stepUp() and stepDown() methods (Read more on MDN)
  • Related