How do I manually trigger a hx-get event of an element from JavaScript
Asked Answered
E

4

10

I am using htmx to add some AJAX calls to my page. I have a cart-count element that is defined to retrieve the number of items in the cart 1s after the page is loaded:

<span id="cart-count" hx-get="/cart/count"
     hx-trigger="load delay:1s" hx-target="#cart-count" hx-swap="outerHTML">
</span>

I also have an add-to-cart button that, after its own stuff (e.g. change itself to remove from cart using htmx), send an extra attribute

    response['HX-Trigger-After-Swap'] = "cart-updated"

to the frontend (see here for the doc).

I have an event listener that works,

document.body.addEventListener("cart-updated",
    function (evt) {
        alert("cart updated")
    })

but how can I trigger hx-get of the #cart-count element in JS?

Note that

hx-trigger="load delay:1s, cart-updated"

would work if the cart stuff is in the parent chain of add-to-cart element, but unfortunately this is not the case for my webpage.

Note that the question is also asked here

Electroform answered 24/1, 2021 at 23:16 Comment(1)
Doc link: htmx.org/headers/hx-trigger To update another part of the page with the same response, we can also use: htmx.org/attributes/hx-swap-oob Also, we can listen for multiple events in the same hx-trigger: htmx.org/attributes/hx-triggerHairbrush
S
16

You can listen for the event on the body of the document in the latest version of htmx using the from: modifier like so:

<span hx-get="/cart/count"
      hx-trigger="load delay:1s, cart-updated from:body" 
      hx-swap="outerHTML">
</span>

Note also that you don't need to use an explicit target here since the default target is the element that the hx-get is defined on.

Scanderbeg answered 24/1, 2021 at 23:25 Comment(0)
C
6

Thank you very much for posting this question and also @1cg for answering! :)

This htmx library is brilliant!

You can check how this server response hx-trigger with django works here: https://github.com/ramiboutas/veryacademy_ecom

Basically when a user adds an item to the basket (or cart), you can pass in the response an event (in the example " updateBasketNumber") like in this view function

@require_http_methods(["PUT", "POST"])
def add_to_basket(request, product_id):
    basket = Basket(request)
    product = get_object_or_404(Product, id=product_id)
    basket.add(product=product)
    response = render(request, 'store/basket/_addedbutton.html')
    trigger_client_event(response, "updateBasketNumber", { },)
    return response

in the html you can add this trigger event to get more info from the server (so you can update the number of items you have in the Basket or Cart):

<div id="basket-number" class="d-inline-flex" 
hx-get="{% url 'basket:update-number' %}" 
hx-trigger="load delay:0.5s, updateBasketNumber from:body">
{% include "store/basket/_number.html" %} 
</div>

I have implemented more trigger events in the tutorial (originally from the Very Academy youtube channel; he uses ajax &js!), you can go to the github repo and check more.

Cabezon answered 28/10, 2021 at 5:53 Comment(0)
B
1

Maybe the JavaScript API could do the trick? I imagine with something like

document.body.addEventListener("cart-updated", function (evt) {
    const c = htmx.values(htmx.find("#cart-count"));
    htmx.ajax('GET', API_URI, { values: { "cart-count": c } })
})
Brand answered 27/2 at 2:6 Comment(0)
K
0

You can easily trigger the event using javascript as follows

document.body.addEventListener("cart-updated",
function (evt) {
    alert("cart updated")
    htmx.trigger("#cart-count", "cart-updated")
})
Karlykarlyn answered 9/7 at 5:35 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.