''This' in a dynamic list using Jquery

I have a script that works for updating plus or minus in a quantity selector in a dynamic list. But I need to convert the code so that it only updates the 'current' list item quantity not all of them in the list.

enter image description here

How can I change the syntax so the following code will only update the one list item quantity, not all of them:

jQuery(document).ready(function(){
    // This button will increment the value
    $('.qtyplus').click(function(e){
        // Stop acting like a button
        e.preventDefault();
        // Get the field name
        var fieldName = $(this).attr('data-plus-number');
        // Get its current value
        var currentVal = parseInt($('input[id='+fieldName+']').val());
        // If is not undefined
        if (!isNaN(currentVal)) {
            // Increment
            $('input[id='+fieldName+']').val(currentVal + 1);
        } else {
            // Otherwise put a 0 there
            $('input[id='+fieldName+']').val(1);
        }
    });
    // This button will decrement the value till 0
    $(".qtyminus").click(function(e) {
        // Stop acting like a button
        e.preventDefault();
        // Get the field name
        var fieldName = $(this).attr('data-minus-number');
        // Get its current value
        var currentVal = parseInt($('input[id='+fieldName+']').val());
        // If it isn't undefined or its greater than 0
        if (!isNaN(currentVal) && currentVal > 1) {
            // Decrement one
            $('input[id='+fieldName+']').val(currentVal - 1);
        } else {
            // Otherwise put a 0 there
            $('input[id='+fieldName+']').val(1);
        }
    });
});

HTML:

<div class="qunatity-inn">
  <input type='button' value='-' class='qtyminus' field='quantity' data-minus-number="updates_large_{{ item.id }}" />
  <input type='number' id="updates_large_{{ item.id }}" name="updates[]" data-name='quantity' value="{{ item.quantity }}" min="1" class='qty quantity-selector' />
  <input type='button' value='+' class='qtyplus' field='quantity' data-plus-number="updates_large_{{ item.id }}" />
</div>


Solution 1:[1]

I'm not sure I understand what you need.

But you want to click the + and - icon and want the closest input field to increase or decrease the current value correctly?

If this is the case, you can go about it this way:

jQuery(document).ready(function() {
  $(document).on('click', '.qtyplus, .qtyminus', function(e) {
    // Detect which class has been clicked.
    let clicked_class = $(this).attr("class");
    // Find the closest element with the class 'quantity-selector'
    let qty_element = $(this).parent().find('.quantity-selector');
    // View the current input value and adjust the value with + or -
    let cur_val = parseInt(qty_element.val()) + (clicked_class === 'qtyminus' ? -1 : +1);
    // update the input value, if the cur_val is 0 or less, add 1 by default (don't allow minus values)
    qty_element.val(!isNaN(cur_val) && cur_val > 0 ? cur_val : 1);
  });
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<div class="qunatity-inn">
  <input type="button" value="-" class="qtyminus" field="quantity" data-minus-number="updates_large_10" />
  <input type="number" id="updates_large_10" name="updates[]" data-name="quantity" value="10" min="1" class="qty quantity-selector" />
  <input type="button" value="+" class="qtyplus" field="quantity" data-plus-number="updates_large_10" />
</div>

<div class="qunatity-inn">
  <input type="button" value="-" class="qtyminus" field="quantity" data-minus-number="updates_large_11" />
  <input type="number" id="updates_large_11" name="updates[]" data-name="quantity" value="10" min="1" class="qty quantity-selector" />
  <input type="button" value="+" class="qtyplus" field="quantity" data-plus-number="updates_large_11" />
</div>

Solution 2:[2]

It might be a good idea to keep track of the count of items in a "state" and just render your view based on that state.

In my snippet, I added the increment/decrement directly to the items in the state (this might not be best practice, but hey! :) ), but you can create actions/mutations that make it cleaner (look for the Flux/Redux pattern).

I would suggest: do NOT keep data in the UI - the UI is (mostly) for presentational purposes, try not relying on data read from it (if possible).

const getItem = () => {
  let _count = 0
  const _id = Date.now()
  return {
    get id() {
      return _id
    },
    get count() {
      return _count
    },
    increment() {
      _count = _count + 1
    },
    decrement() {
      _count = _count - 1
    },
  }
}

const state = {
  items: []
}

const getItemTemplate = (item) => `
  <div data-id="${item.id}">
    ${item.id}:
    <button class="decrement">-</button>
    ${item.count}
    <button class="increment">+</button>
  </div>
`

const getItemsHtml = ({ items }) => items.map(getItemTemplate).join('')

const updateItemsList = (selector) => (html) => jQuery(selector).html(html)

const updateItemsContainer = updateItemsList(".container")

const updateView = (state) => {
  const itemList = getItemsHtml(state)
  updateItemsContainer(itemList)
}

const getItemFromList = (thisItem) => {
  const thisId = jQuery(thisItem).parent().attr("data-id")
  return state.items.find(({ id }) => id == thisId)
}

jQuery(document).ready(function($) {
  $("#btn-add-item").on("click", function() {
    state.items = [...state.items, getItem()]
    updateView(state)
  })

  $(".container").on("click", ".increment", function() {
    const item = getItemFromList(this)
    item.increment()
    updateView(state)
  })

  $(".container").on("click", ".decrement", function() {
    const item = getItemFromList(this)
    item.decrement()
    updateView(state)
  })

})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button id="btn-add-item">ADD ITEM +</button>
<div class="container"></div>

EDIT

Another solution could be that you search for which item you are clicking when the click is done:

const itemTemplate = `
  <div class="qunatity-inn">
    <input type='button' value='-' class='qtyminus' field='quantity' data-minus-number="updates_large_{{ item.id }}" />
    <input type='number' id="updates_large_{{ item.id }}" name="updates[]" data-name='quantity' value="{{ item.quantity }}" min="1" class='qty quantity-selector' />
    <input type='button' value='+' class='qtyplus' field='quantity' data-plus-number="updates_large_{{ item.id }}" />
  </div>
`

jQuery(document).ready(function($) {
  $("#btn-add-item").on("click", function() {
    $(".container").append(itemTemplate)
  })
  $(".container").on("click", ".qtyminus", function() {
    const input = $(this).parent().find(".quantity-selector")
    input.val(Number(input.val()) - 1)
  })
  $(".container").on("click", ".qtyplus", function() {
    const input = $(this).parent().find(".quantity-selector")
    input.val(Number(input.val()) + 1)
  })
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button id="btn-add-item">ADD ITEM</button>
<div class="container">
</div>

Solution 3:[3]

The answer to this question was solved. It was a Shopify For-Loop issue not a Jquery issue. My Jquery code and your suggestions are all correct. The problem was elsewhere.

Thank you!!

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2
Solution 3 Pacarus