putyourlightson / craft-sprig

A reactive Twig component framework for Craft CMS.
https://putyourlightson.com/plugins/sprig
MIT License
124 stars 9 forks source link

Refresh another component after an action #20

Closed billmn closed 3 years ago

billmn commented 3 years ago

Hi there, I would refresh a navbar component (Cart icon with total of elements inside it) when a product was added to the cart.

Anyone can help me figure out how to do it?

<!-- Component 1: Add to cart button -->
<form sprig s-method="post" s-action="commerce/cart/update-cart">
    <input type="hidden" name="purchasableId" value="{{ variantId }}">
    <button type="submit">Add to cart</button>
</form>

<!-- Component 2: Icon in the navbar with number of items in the cart -->
<div id="cart-icon">
    {{ cart.lineItems|length }}
</div>

Schermata 2020-08-17 alle 15 46 14

bencroker commented 3 years ago

To achieve this you would first need to assign your components an ID so you can reference them. Then, since every component has an event trigger called refresh by default, you could trigger the Cart component to refresh after the Add to Cart component AJAX request has been successfully loaded.

{{ sprig('cart', [], {id: 'cart'}) }}
{{ sprig('add-to-cart', [], {id: 'add-to-cart'}) }}

<script>
htmx.on('htmx:afterOnSwap', function(event) {
    if (event.detail.target.id == 'add-to-cart') {
        document.getElementById('cart').dispatchEvent(new Event('refresh'));
    }    
});
</script>
billmn commented 3 years ago

Thank you Ben, it works fine!

kerns commented 3 years ago

@bencroker I want to accomplish more or less the same thing with adding/removing items in Wishlist. So items added/removed are displayed in a menu without the need for a reload.

I'll be following this example but will also be watching your recipe section to see if a more advanced behavior like this makes an appearance. ;)

bencroker commented 3 years ago

I do plan on adding an example to the cookbook, the reason I'm waiting is that the htmx event names will likely be changed in the near future and I don't want to cause more confusion than necessary. Hopefully the example above should get you there for now though.

bencroker commented 3 years ago

Added a "Refreshing Components" recipe at https://putyourlightson.com/sprig-cookbook#refreshing-components.

gazlawn22 commented 3 years ago

@bencroker and @billmn any chance you could share some more of your template files for this, I'm struggling to make this work, currently using:

{{ sprig('_components/add-to-cart', {id: 'add-to-cart', variantId: variant.id }) }}

This lets me add to cart via sprig basically with any form I want, including billmn's initial form, however then introducing the basket count and trying to update that component too, I get absolutely nothing on the basket count front, adding the product still works though...

I'm adding the cart component with the following:

{{ sprig('_components/cart', {id: 'cart', cartId: cart.id }) }}

Which loads...

{% set cart = craft.orders.id(cartId).one() %} {{ cart.lineItems|length }}

Presuming I am doing something really obvious wrong , but any help would be appreciated? I've been including botg rge hyperscript and script tags too.

bencroker commented 3 years ago

Note that the attributes (including the ID) go in the third parameter, as per the recipe:

{{ sprig('_components/counter', {}, {'id': 'counter'}) }}
gazlawn22 commented 3 years ago

Do you mean more like this?

{{ sprig('_components/add-to-cart',{}, {id: 'add-to-cart', variantId: variant.id }) }}

As then I just get a variantId does not exist in my add-to-cart template?

{% set variantId = craft.variants.id(variantId).one() %}
<form sprig s-method="post" s-action="commerce/cart/update-cart">
    <input type="hidden" name="purchasableId" value="{{ variantId }}">
    <label for="qty">
        <span class="label">Quantity</span>
        <input type="number" name="qty" id="qty" min="1" value="1">
    </label>
    <input type="submit" class="dc_button" value="Add to cart">
</form>

And i've tried quite a few ways of defining that variantId?

billmn commented 3 years ago

No, only the id in the third parameter, like this:


{{ sprig('_components/add-to-cart',{
   variantId: variant.id
}, {
   id: 'add-to-cart'
}) }}
bencroker commented 3 years ago

Exactly. Read up on component variables and attributes in the docs.

gazlawn22 commented 3 years ago

Thanks for clearing that up, It's now back to submitting as I had before, but the right way :-), the cart number wasn't updating using, however I've tracked it down and my got that working now so thanks!

bencroker commented 3 years ago

Great!