'HTMX, Django - update part of page

I've started with HTMX and I want to use it to refresh part o page after pressing button on pop-up page. The button is adding clicking user as participant in an event. I going true tutorials and example which mostly present cases with forms and I don't know how to approach this update with it.

I'm pretty sure I should use hx-ws, but it is just completely unclear for me how.

chall-interface.html (here is a part which I want to update)

{% load static %}
{% load tagz %}

<div id='chall-interface' class="card-bottom mb-2">
  <button onclick="call('challFollows',{'id':'{{chall.id}}'}, this)" class='icon icon-s rounded-sm float-end background-transparent mb-2 me-1 color-white'><i  class="font-12 fa fa-heart {% followedChall user chall %}"></i></button>
  <button href="#" data-menu="comment-section"  class="icon icon-s rounded-sm float-end background-transparent mx-1 mb-2">
      <i class="font-12 fa fa-comments color-white"></i>
  </button>
  {% if chall.dealine_is_over %}
      <button href="#" data-menu="rules" class="icon icon-s rounded-sm float-end background-transparent mx-1 mb-2">
          <i class="font-12 fa color-white {% changeJoinButton user chall %}""></i>
      </button>
      <!-- Here is a code I'm asking about -->

      {% if user == userParticipationStatus.user %}
      <a href="/addResponse/{{chall.id}}" class="icon icon-s rounded-sm float-end background-transparent mx-1 mb-2">
          <i class="font-12 fa fa-plus-square color-white"></i>
      </a>
      {% else %}
      {% endif %}

      <!-- Here is a code I'm asking about -->
      {% if chall.user == user %}
      <button class="icon icon-s rounded-sm float-end background-transparent mx-1 mb-2">
          <i class="font-12 fa fa-pen color-white"></i>
      </button>
      {% else %}
      {% endif %}
  {% else %}
  {% endif %}
  <div class="card-bottom mb-1 w-25">
    {% if chall.profile.id == None %}
    <a href='#'><img src="{% static 'images/avatars/5s.png' %}" class="float-start border border-white bg-yellow-light rounded-circle ms-3" width="35"></a>
    {% elif chall.user == user %}
    <a href='/profile/'><img src="{% static 'images/avatars/5s.png' %}" class="float-start border border-white bg-yellow-light rounded-circle ms-3" width="35"></a>
    {% else %}
    <a href='/userProfile/{{chall.profile.id}}'><img src="{% static 'images/avatars/5s.png' %}" class="float-start border border-white bg-yellow-light rounded-circle ms-3" width="35"></a>
    {% endif %}
    <span class="float-start mx-3"><i>{{chall.profile.nickname}}</i></span>
  </div>
</div>

It is added as {% include "include/chall-interface.html" %} in main html file from which a pop-up is activated

Here is a pop-up

{% load tagz %}
<div id="rules" class="menu menu-box-modal rounded-m" data-menu-width="350">
  <div class="card card-style" style="margin: 0px !important">
    <div class="content">
      <strong class="font-12 mx-1">Rules</strong>
      <span class="color-theme font-14 d-block mx-1">{{chall.rules}}</span>
      <!-- This is the button -->
      <button  onclick="call('challParticipates',{'id':'{{chall.id}}'}, this)" class="close-menu btn btn-m float-end rounded-xl shadow-xl text-uppercase font-800 bg-highlight mx-1 my-2"><i>{% changeJoinButton2 user chall %}</i></button>
      <!-- This is the button -->
      <button data-bs-dismiss="modal" class="close-menu btn btn-m float-end rounded-xl shadow-xl text-uppercase font-800 bg-highlight mx-1 my-2"><i>Exit</i></button>
    </div>
  </div>
</div>

Here is a call function activated by the button:

function call(url, info, element) {
  eventStatus = false
  fetch("/"+url+"/", {
      method: 'POST',
      headers: {'X-CSRFToken': getCookie('csrftoken')},
      body: JSON.stringify(info)
    }).then(response => response.text())
      .then(responseData => {
        dataParsed = JSON.parse(responseData);
        console.log(dataParsed)
        if (dataParsed.eventStatus) {
          element.firstElementChild.classList.add("color-gold");
          element.firstElementChild.classList.remove("color-white");
        }
        else {
          element.firstElementChild.classList.remove("color-gold");
          element.firstElementChild.classList.add("color-white");
        }
      })
      .catch(err => {
          // if any error occured, then catch it here
          console.error(err);
      });
}

View.py

class ChallView(LoginRequiredMixin, TemplateView):
    login_url = '/chalth/login'
    redirect_field_name = ''

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        chall = Chall.objects.get(id=kwargs.get("id"))
        context['chall'] = chall
        currentUser = self.request.user
        context['userParticipationStatus'] = Participates.objects.filter(user = currentUser, chall = chall).first()
        return context

@login_required(login_url = '/chalth/login')
def ChallParticipatesView(request):
    data = json.loads(request.body)
    id = data.get("id", False)
    if id:
        challParticipate = Participates.objects.filter(chall_id=id, user=request.user).first()
        eventStatus = False
        if challParticipate:
            challParticipate.delete()
            eventStatus = False
        else:
            challParticipate=Participates()
            chall = Chall.objects.get(id=id)
            eventStatus = True
            if chall:
                challParticipate.chall = chall
                challParticipate.user = request.user
                challParticipate.save()
            else:
                return HttpResponse(status = 400)
    else:
        return HttpResponse(status = 400)
    return HttpResponse(json.dumps({"eventStatus": eventStatus, "id": id}), status = 200)


Solution 1:[1]

As far as I can understand from your code, I can't see htmx in action.

I suggest you first try using the inline way, for example:

<button hx-post="/clicked"
    hx-trigger="click"
    hx-target="#parent-div"
    hx-swap="outerHTML"
>
    Click Me!
</button>

to see if your problem is about:

  • the server that doesn't return valid HTML
  • the server that returns an error (that will stop the swap)
  • the wrong usage of htmx APIs

Also make sure to know what the properties:

  • hx-trigger
  • hx-target
  • hx-swap

do.

I hope I have helped ?

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 Luca Fedrizzi