skip to Main Content

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 class="cart-items-number d-flex ml-auto" method='POST' action=''>
<input type = "submit" value="-" name = "submit" value = "Submit" class="qtyminus btn btn-success btn-sm" 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 class="cart-items-number d-flex ml-auto" method='POST' action=''>
<input type = "submit" value="-" name = "submit" value = "Submit" class="qtyminus btn btn-success btn-sm" 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>

2

Answers


  1. 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 class="cart-items-number d-flex ml-auto" method='POST' action=''>
        <input
          type="button"
          value="-"
          name="minus"      
          class="qtyminus btn btn-success btn-sm"
          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 class="cart-items-number d-flex ml-auto" method='POST' action=''>
          <input
          type="button"
          value="-"
          name="minus"      
          class="qtyminus btn btn-success btn-sm"
          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>
    Login or Signup to reply.
    • 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 class="cart-items-number d-flex ml-auto" method='POST' action=''>
      <button type="button" class="qtyminus btn btn-success btn-sm">-</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 class="cart-items-number d-flex ml-auto" method='POST' action=''>
      <button type="button" class="qtyminus btn btn-success btn-sm">-</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)
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search