jeudi 2 juin 2022

StimulusJS how to compute value in parent controller from values in different child controllers (cart -> cart items)

I am building a cart with stimulus. The cart recap page displays multiple cart items. A cart item has a unit price and a quantity. Each cart item component has a quantity selector, when the quantity number changes the total price of the cartitem element is recalculated totalCartItem = unitPrice x Quantity and the total price if the cart must also be recalculated totalCartPrice = sum(totalCartItem)

Here's a simplification of the html structure

<div class="cart" data-controller='cart'>
  <div class="cart-item" data-controller='cart-item'>
    <p class='unit-price'>20</p>
    <input type="number" name="quantity" value="1">
    <p class='total-price' data-target='cart-item.totalPrice' data-action="change->cart-item#update" data-target='cart-item.quantity'>20</p>
  </div>
  <div class="cart-item" data-controller='cart-item'>
    <p class='unit-price'>10</p>
    <input type="number" name="quantity" value="2" data-action="change->cart-item#update" data-target='cart-item.quantity'>
    <p class='total-price' data-target='cart-item.totalPrice'>20</p>
  </div>
  <div class="cart-total">
    40
  </div>
</div>

My cart item controller works perfectly fine and updates correctly the totalPriceFor a cart item in the UI.

export default class extends Controller {
  static targets = ["totalPrice", "quantity"]

  static values = {
    unitPrice: String,
  }

  connect() {
    console.log("hello from StimulusJS")
  }

  update(){
    this.totalPriceTarget.textContent = parseFloat(this.unitPriceValue) * parseInt(this.quantityTarget.value)
  }
}

However, I am now lost on how to update the totalCartPrice. I feel like this should be the responsability of the cartController that wrapps the cartItems elements, but I have no idea on what id the correct way to achieve this. I feel like I should add change->cart#update on each number input selector for quantity for each cart-item, but then what should I add to the cart#update method to recalculate the total from each individual cart item ?

export default class extends Controller {
  static targets = ["total"]
  connect() {
    console.log("hello from StimulusJS")
  }

  update(){
    // let details = event.detail;
    // this.cartItemChildren.forEach((item) => console.log(item.totalValue))
  }
}

Aucun commentaire:

Enregistrer un commentaire