skip to Main Content

I am currently working on a quantity picker for an eCommerce. The quantity picker consists of:

  1. The minus button
  2. The quantity input field: every time the user clicks on either of the quantity buttons, the value gets updated
  3. The quantity text: this is the quantity enclosed in <span> tags
  4. The plus button

Here is the HTML layout for the quantity picker:

<div class="product-form__input product-form__quantity">
  <label class="form__label">
    Quantity
  </label>

  <button class="quantity__button minus no-js-hidden" name="minus" type="button" disabled>
    -
  </button>

  <input class="quantity__input"
  type="number"
  name="quantity"
  id="Quantity-{{ section.id }}"
  min="1"
  value="1"
  form="{{ product_form_id }}"
  >

  <span class="quantity__text">1</span>

  <button class="quantity__button plus" name="plus" type="button">
    +
  </button>
</div>

The JavaScript is as shown below, where quantityPicker.init() is called which includes:

  • Updating the value of the quantity input field everytime the user clicks on the plus or minus quantity buttons (call the quantityPicker.onButtonClick() function)
  • When the value of the quantity input field changes, the quantityPicker.onChange() function must be called.
// Quantity picker
let
  quantityFields = document.querySelectorAll(".quantity__input"),
  quantityButtons = document.querySelectorAll(".quantity__button"),
  quantityPicker = {
    onButtonClick: function (event) {
      let
        button = event.target,
        picker = button.closest(".product-form__quantity"),
        quantity = picker.querySelector(".quantity__input"),
        quantityValue = parseInt(quantity.value),
        max = quantity.getAttribute("max") ? parseInt(quantity.getAttribute("max")) : null

        if (button.classList.contains("plus") && (max === null || quantityValue + 1 <= null)) {
          quantity.value = quantityValue + 1
        }
        else if (button.classList.contains("minus")) {
          quantity.value = quantityValue - 1
        }
    },
    onChange: function (event) {
      let
        field = event.target,
        picker = field.closest(".product-form__quantity"),
        quantityText = picker.querySelector(".quantity__text"),
        shouldDisableMinus = parseInt(event.target.value) === parseInt(field.getAttribute("min")),
        shouldDisablePlus = parseInt(event.target.value) === parseInt(field.getAttribute("max")),
        minusButton = picker.querySelector(".quantity__button.minus"),
        plusButton = picker.querySelector(".quantity__button.plus")
        
      quantityText.innerText = event.target.value

      if (shouldDisableMinus) {
        minusButton.setAttribute("disabled", "disabled")
      } else if (minusButton.getAttribute("disabled") === true) {
        minusButton.removeAttribute("disabled")
      }

      if (shouldDisablePlus) {
        plusButton.setAttribute("disabled", "disabled")
      } else if (plusButton.getAttribute("disabled") === true) {
        plusButton.removeAttribute("disabled")
      }
    },
    init: function () {
      // when a button is clicked
      quantityButtons.forEach(quantityButton => {
        quantityButton.addEventListener("click", function (event) {
          quantityPicker.onButtonClick(event)
        })
      })

      // when a quantity is changed
      console.log(quantityFields)

      quantityFields.forEach(quantityField => {
        console.log(quantityField)

        quantityField.addEventListener("change", function (event) {
          console.log("Value changed!")
          quantityPicker.onChange(event);
        })
      })
    }
  }

  quantityPicker.init()

However, the issue I am experiencing is that even though the value changes when I click on the plus or minus buttons (as indicated by the change in value on the screen), the change event is not working.

The event only fires if I directly type in a value into the input, and then press the Enter / return key. How can I call the quantityPicker.onChange() function every time the value gets updated, without having to press the return key?

2

Answers


  1. Chosen as BEST ANSWER

    I figured out the solution for this question. The change nor the input events will not work if they are changed programmatically. In order to trigger the events, I had to use the dispatchEvent() function to trigger those events programmatically, as shown below:

    quantity.dispatchEvent(new Event('input'));
    

  2. Consider using input event. It fires on every input

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search