https://htmx.org logo
Join Discord
Powered by
# πŸ”₯-django-htmx
  • h

    handsome-shampoo-48908

    05/17/2023, 9:45 AM
    html
    Copy code
    html
    <div class="container mx-auto mt-5">
        <header class="d-flex align-items-center gap-2 mb-5">
            <img src="https://cdn-icons-png.flaticon.com/128/2666/2666436.png" alt="ToDo List">
            <h1 class="mb-0">To Do List</h1>
        </header>
    
        <hr>
        <br>
    
        <div class="row justify-content-around">
            <div class="card col-sm-6 col-md-4 col-lg-4 mb-5">
                <h5 class="card-header">Collections</h5>
                <div class="card-body">
                    <nav id="collections" class="list-group">
                        {% for collection in collections %}
                        {% include 'tasks/collection.html' with collection=collection %}
                        {% endfor %}
                    </nav>
                        <form method="POST" class="d-flex gap-2 mt-2">
                            {% csrf_token %}
                            {{ form_collection.name }}
                            <button class="btn btn-success"
                                    hx-post="{% url 'add-collection' %}"
                                    hx-target="#collections"
                                    hx-swap="beforeend"
                                    type="submit">Add
                            </button>
                        </form>
                </div>
            </div>
  • h

    handsome-shampoo-48908

    05/17/2023, 9:45 AM
    Copy code
    html
          <div class="card col-sm-6 col-md-6 col-lg-6 mb-5">
                  <h5 class="card-header">Tasks</h5>
                <div class="card-body">
                    <form method="POST" name="task-form" class="d-flex gap-2 mt-2" id="task_form">
                        {% csrf_token %}
                        {{ form_task.description }}
                        <button class="btn btn-success"
                                hx-post="{% url 'add-task' %}"
                                hx-target="#tasks"
                                hx-vals='js:{collection: getCollectionFromURL()}'
                                hx-swap="beforeend"
                                type="submit"
                        >Add
                        </button>
                    </form>
                    <section id="tasks-container">
                        {% include 'tasks/tasks.html' with tasks=tasks collection=collection %}
                    </section>
                </div>
            </div>
        </div>
    </div>
  • h

    handsome-shampoo-48908

    05/17/2023, 9:45 AM
    Copy code
    html
    <script>
        document.body.addEventListener("htmx:afterRequest", (event) => {
            document.querySelector(".reset-field-collection-form").value = '';
        })
    
        document.body.addEventListener("htmx:afterRequest", (event) => {
            document.querySelector(".reset-field-task-form").value = '';
        })
    
        document.body.addEventListener("htmx:responseError", (event) => {
            alert(evt.detail.xhr.responseText);
        })
    
        function getCollectionFromURL() {
            let url = new URL(window.location.href);
            let searchParams = url.searchParams;
            return searchParams.get("collection");
        }
    
        document.body.addEventListener('htmx:configRequest', (event) => {
            event.detail.headers['X-CSRFToken'] = '{{ csrf_token }}';
        })
    
    
    </script>
  • m

    mammoth-family-48524

    05/17/2023, 10:08 AM
    I made something which I think is pretty cool https://github.com/benopotamus/okayjack-htmx. It's an HTMX extension + Django middleware and HttpResponse classes. It lets me specify different hx attributes for success and error, and also specify the path to a file or template block for success and error responses. Then in the Django view, I can just say whether a response should be treated as an error or success, and HTMX will update the page accordingly. Fair warning though, I'm just hacking away at things and I haven't tested it extensively - just a bit πŸ˜„
  • w

    white-motorcycle-95262

    05/17/2023, 2:14 PM
    Looking for some feedback/suggestions on a pattern I'm trying to implement. The concept is a "dashboard" that has easy to plug in "widgets." Currently, each widget is a template fragment based around Bootstrap `.card`s. Each widget has
    hx-
    attributes that listen for a particular
    change
    event (all coming from a single form, usually just has two fields: a select for the "region" and a toggle for the "timespan", short or long term). All widgets are tied to a class based "WidgetView" that has methods for generating the HTML associated with each type of widget. The idea is that to create a dashboard, all I have to do is create a base template with columns/rows and put
    {% include 'widgets/widget_name.html' %}
    where I want my widgets to go. This works, but it results in a single request for each widget, which I'm not opposed to, but in reality the widgets are quite coupled together: they always change all at the same time, and there's a small amount of "setup" code+database hits that end up being duplicated each request. I suppose the alternate way would be to put the
    hx-
    attributes on the form and do OOB swaps, which would result in a single request. My question is: what can I do on the form to communicate to the server which widgets are present on the dashboard? The only thing I've thought up involves hyperscript:
    Copy code
    <form
      id="control-panel
      hx-get="/widgets"
      _="
      init
        set widgets to {}
        for widget in <[data-widget]/>
          set widgets[widget's @id] to widget's @data-widget
        end
        set my @hx-vals to widgets as JSON
      end
    >[...]</form>
    where each widget would have a
    data-widget
    attribute that specifies the widget's "type" (e.g., map, graph, table, etc). Any thoughts or criticisms on this approach would be appreciated πŸ™‚
  • b

    brave-dog-98297

    05/17/2023, 9:27 PM
    If your template has which widget goes where, all you need is to send the correct data from the backend along with your base and Django will render it in one request. That's if I'm understanding correctly and they will update at the same time. I'd setup a div in the body with all the hx attributes and post/get from there.
  • w

    white-motorcycle-95262

    05/17/2023, 11:30 PM
    Hmm, but if I have multiple different views that have different layouts for the widgets (and potentially different choices of widgets for each view), how will the different views know how to render each widget (e.g. process the necessary context for each template). Currently, each view is just responsible for rendering the base template (e.g, which widgets and where), then after all those empty widgets load, htmx fetches the (non empty) widgets from my WidgetView.
  • b

    brave-dog-98297

    05/17/2023, 11:38 PM
    If they are all updating simultaneously I would push the heavy lifting to the template engine where possible* to avoid too many requests. But this may not work in your case. Your template can include other templates, as long as the data gets to the base template it should work
  • w

    white-motorcycle-95262

    05/17/2023, 11:40 PM
    Yeah, I'll try to implement something that only uses one request. Thanks!
  • p

    plain-kangaroo-26043

    05/19/2023, 5:18 PM
    So inspired by this article https://valberg.dk/django-sse-postgresql-listen-notify.html on using StreamingHttpResponse with PostgreSQL NOTIFY/LISTEN, I worked on a simple chat implementation using HTMX SSE extension: https://github.com/danjac/dissonance
  • g

    gray-rocket-3571

    05/20/2023, 4:16 PM
    Love this kind of stuff. I was just reading the original article and got to the JS part and thought β€œhmmm htmx has SSE I wonder”…checked this discord and boom. Nicely done.
  • h

    happy-microphone-42295

    05/23/2023, 6:21 PM
    @htmx_org multi-swap extension, swapping multiple elements from the HTML response: constructed with django+python code in forms+views+templates #htmx #django #python https://cdn.discordapp.com/attachments/864934037381971988/1110633496290005072/VID-20230523-WA0002.mp4
  • w

    white-motorcycle-95262

    05/24/2023, 1:00 PM
    I'm blanking: if I have a form such as
    Copy code
    py
    <form
      hx-get="/my_url/"
      hx-trigger="change"
    >
      <select id="id_region" name="region">[...]</select>
      <select id="id_timespan" name="timespan">[...]</select>
    </form>
    Is there a way actually fetch
    /my_url/[region.value]/[timespan.value]/
    ? Does it require hyperscript? Something like
    Copy code
    py
    <form
      hx-get="/my_url"
      hx-trigger="customChange"
      _="
        on change
          set my @hx-get to `${@hx-get}/${#id_region's value}/${#id_timespan's value}`
          trigger customChange on me
        end
      "
    >[...]</form>
  • g

    great-cartoon-12331

    05/24/2023, 3:56 PM
    by default no, but it will submit
    /my_url/?region=[region.value]Γ—pan=[timespan.value]
    , so you could handle that
  • w

    white-motorcycle-95262

    05/24/2023, 4:05 PM
    Yeah, that's what I was initially doing, but I think I want to "simplify" the URLs be more non-coder friendly
  • l

    limited-teacher-83117

    05/24/2023, 4:13 PM
    what's more non-coder friendly about simpler URLs?
  • w

    white-motorcycle-95262

    05/24/2023, 4:16 PM
    I mean, I prefer to tell people to go to
    /dashboard/texas/current/
    as opposed to
    /dashboard?region=texasΓ—pan=current
  • w

    white-motorcycle-95262

    05/24/2023, 4:17 PM
    and I feel like the first option is more inline with what a URL "should" be, than the second πŸ€·β€β™‚οΈ
  • l

    limited-teacher-83117

    05/24/2023, 4:24 PM
    I don't have any data, but I'd question that assumption for two reasons: 1. People typically don't edit URLs or even type them out, it's a click or nothing. google's biggest searches are just people typing "facebook" to go to facebook.com 2. To the extent that people do think about what a more complex URL represents, they are by far most likely to have thought about it in the context of a google link, which uses the traditional query structure
  • l

    limited-teacher-83117

    05/24/2023, 4:25 PM
    it's possible i'm just engineer-brained, but the second one actually looks more normal to me (i.e. like a google link) and also says more about what the different parameters represent (region? texas. timespan? current)
  • g

    great-cartoon-12331

    05/24/2023, 4:26 PM
    hmm yeah, people are not going to manually type out URLs. at best they'll scan a QR code πŸ™‚
  • w

    white-motorcycle-95262

    05/24/2023, 4:32 PM
    Yeah, fair. Maybe the former one looks more "hypermedia friendly" to me. Given that URL is "uniform resource locator" and the "current texas dashboard" is located at the url
    /dashboard/texas/current
    . πŸ€·β€β™‚οΈ
  • g

    great-cartoon-12331

    05/24/2023, 4:34 PM
    you could argue either way. e.g.
    /current
    doesn't point to a single resource by its ID, which we can say is contra to REST
  • w

    white-motorcycle-95262

    05/24/2023, 4:36 PM
    Why do you say that
    /dashboard/texas/current/
    doesn't point to a single resource? I'm a bit unfamiliar with the terminology
  • g

    great-cartoon-12331

    05/24/2023, 4:37 PM
    a resource needs to be specified by its ID, right?
    /current
    is not an ID, it's a pointer
  • w

    white-motorcycle-95262

    05/24/2023, 4:39 PM
    Oh, I see. I think I need to look up the definitions of "resource", "id", and "pointer" in this context. Do you mean "id" in the sense that a URL would have to end in
    /blah/#element_id
    ?
  • g

    great-cartoon-12331

    05/24/2023, 4:42 PM
    no i mean a unique identifier of a resource. what that means exactly is defined by your application. not an HTML
    id
    attribute specifically although you can render a resource with HTML and use an
    id
    attribute
  • l

    limited-teacher-83117

    05/24/2023, 4:46 PM
    you can also just have your server read the second URL and 303 to the first one, which should be trivial
  • w

    white-motorcycle-95262

    05/24/2023, 4:46 PM
    Yeah, I just had that thought while trying to get this to work with hyperscript lol
  • l

    limited-teacher-83117

    05/24/2023, 4:47 PM
    rediscovering redirects as the idiomatic way to deal with page "state" has been a game changer for me