HTMX not loading

I just started trying to implement HTMX into an existing Django app. What I think should be the easiest step of all is causing me the most problems, and I’m sure it’s a very simple solution that is just escaping me somehow.

I can’t seem to get the HTMX JS code to be included in my app. I’ve added it to Main.html which is included in all templates. I tried using the CDN as well as downloading the min version and putting it into my static/JS folder.

The “load” process that I have here does not get called.

    <div hx_get="/albums/album_partial_gallery/" hx_trigger="load">
        Loading gallery...
    </div>

I’m using the following code to test whether or not it is loaded.

    if request.headers.get('HX-Request'):
        htmx=False
    else:
        htmx=True

Here is where I am including the HTMX JavaScript…

<script src="{% static 'js/htmx.min.js' %}"></script>
</body>
</html>

Is this a development environment, or a production deployment environment?

What specific directory is htmx.min.js in?

What is the html that was rendered for that script tag?
What request are you seeing on the server for this file?

This is in a development environment (localhost:8000).

The html for the script tag looks like this…

<script src="/static/js/htmx.min.js"></script>

This is where the htmx.min.js is located. However, I also tried including…

<script src="https://unpkg.com/htmx.org@2.0.0"></script>

in the head section.

The initial view on the server loads fine and renders the page correct, but it does not recognize that htmx is included in the headers.

The second view, album_partial_gallery, which should be called by the “load” event in the htmx tag never gets called.

Please be specific, exactly what complete directory is htmx.min.js located in?

How does that fit in with your project directory structure?

What is your browser telling you about this request? Is it successful?

Here is the folder to the htmx.min.js file.

C:\Users\bob\Documents\Python-Django\Ursus\static\js

I also have another JavaScript module/file in this same folder and I added

console.log('Hello, World!);

to that code just to make sure it was being included, and that text does appear in the console.

When I used the alternate script tag (unpkg.com) I did not get any communication from the browser that the include had failed, however, the code I used to test the presence of ‘HX-Request’ still returned False.

But what about confirmation that the request worked?
What about confirmation that the file was retrieved and loaded?

We may need to see the complete template, and any parent templates that this extends.

Here is the full template…

{% extends 'main.html' %}

{% block content %}

    {% load static %}

    <h3 class="text-warning bg-secondary px-5 pt-2 pb-2">Album Gallery</h3>

    <div class="container-mt-4 d-flex align-items-center justify-content-center">
        {% if show_list %}
            <a href="{% url 'albums' %}" title="Return to Album List">
                <button type="button" class="btn btn-primary" style="width: 250px;">Return to Album List</button>
            </a>
        {% else %}
            <a href="{% url 'albums_grid' %}" title="Return to Album Grid">
                <button type="button" class="btn btn-primary" style="width: 250px;">Return to Album Grid</button>
            </a>
        {% endif %}
        &nbsp;
{#        <a href="{% url 'album_sections' album_object.id source %}">#}
{#            <button type="button" class="btn btn-primary" style="width: 250px;">Return to Chapter List</button>#}
{#        </a>#}
    </div>

    <div>
        {{ htmx_status }}
    </div>

    <div hx_get="/albums/album_partial_gallery/" hx_trigger="load">
        Loading gallery...
    </div>


{% endblock content  %}

Here is the view that loads this template…

def album_gallery_test(request, album_section_id):
    source = request.session['album_source']
    show_list = True
    if source == 'grid':
        show_list = False
    if request.headers.get('HX-Request'):
        htmx=True
    else:
        htmx=False
    context = {
        "source": source,
        "show_list": show_list,
        "htmx_status": htmx,
    }
    return render(request, 'Albums/albums_lazy_images.html', context)

Here is the code that should be called from the “load” event but I confirmed from the debugger that it never gets here…

def album_partial_gallery(request):
    time.sleep(2)
    context = {}
    return render(request, 'Albums/Partials/album_images.html',context)

Please let me know if you need to see anything else.

Thanks.

We also need to see the extended “main.html” template

Here is main.html

<!DOCTYPE html>
{% load static %}
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
    {#    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN" crossorigin="anonymous">#}

    <link rel="stylesheet" type="text/css" href='{% static "styles/styles.css" %}'>
    <link rel="stylesheet" type="text/css" href='{% static "styles/bootstrap.css" %}'>
    <link rel="stylesheet" type="text/css" href='{% static "styles/font-awesome.css" %}'>
    <link rel="stylesheet" type="text/css" href='{% static "styles/main.css" %}'>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css">
    <title>Ursus</title>
</head>
<body>
{% include 'navbar.html' %}

{% if messages %}
    {% for message in messages %}
        {% if message.tags == "success" %}
            <div id="myAlert" class="alert alert-success alert-dismissible fade show" role="alert">
                <strong>Note!</strong> {{ message }}
                <button type="button" class="btn-close btn-success" data-bs-dismiss="alert" aria-label="Close"></button>
            </div>
        {% endif %}
        {% if message.tags == "warning" %}
            <div id="myAlert" class="alert alert-warning alert-dismissible fade show" role="alert">
                <strong>Warning!</strong> {{ message }}
                <button type="button" class="btn-close btn-warning" data-bs-dismiss="alert" aria-label="Close"></button>
            </div>
        {% endif %}
        {% if message.tags == "error" %}
            <div id="myAlert" class="alert alert-danger alert-dismissible fade show" role="alert">
                <strong>Error!</strong> {{ message }}
                <button type="button" class="btn-close btn-danger" data-bs-dismiss="alert" aria-label="Close"></button>
            </div>
        {% endif %}
    {% endfor %}
{% endif %}

{% block content %}

{% endblock content %}

<div class="mt-5">
    <div class="footer bg-success py-2">
        <div class="container">
            <div class="row">
                <div class="col-md-4 my-3">
                    <h6>About Ursus</h6>
                    <p>
                        Litora nullam nec elit mus phasellus tempus rutrum lorem inceptos arcu. Maecenas tristique justo
                        potenti risus ac aliquet fusce arcu etiam. Senectus quis odio natoque taciti maximus si nullam
                        conubia vel mattis. </p>
                </div>
                <div class="col-md-4 my-3">
                    <h6>Links</h6>
                    <ul class="list-unstyled">
                        <li>
                            Useful: <a href="#">Expertise</a>,
                            <a href="#">Pricing</a>
                        </li>
                        <li>
                            Menu: <a href="{% url 'albums' %}">Home</a>, <a href="#">Details</a>,
                            <a href="#">Solutions</a>,
                            <a href="{% url 'profile' %}">Profile</a>
                        </li>
                    </ul>
                </div>
                <div class="col-md-4 my-3">
                    <div class="mb-4">
                        <a href="#" class="text-decoration-none" tooltip="Meta/Facebook">
                            <i class="bi bi-meta main-icons"></i>
                        </a>
                        <a href="#" class="text-decoration-none" tooltip="X/Twitter">
                            <i class="bi bi-twitter-x main-icons"></i>
                        </a>
                        <a href="#" class="text-decoration-none" tooltip="Linked-In">
                            <i class="bi bi-linkedin main-icons"></i>
                        </a>
                        <a href="#" class="text-decoration-none" tooltip="Youtube">
                            <i class="bi bi-youtube main-icons"></i>
                        </a>
                        <a href="#" class="text-decoration-none" tooltip="Dropbox">
                            <i class="bi bi-dropbox main-icons"></i>
                        </a>
                    </div>
                    <p>
                        We would love to hear from you
                        <a href="mailto:contact@site.com"
                        ><strong>contact-us@ursus.io</strong></a
                        >
                    </p>
                </div>
            </div>
        </div>
    </div>
</div>

<script type="text/javascript">
    $(function () {
        $(".close").click(function () {
            $("#myAlert").alert();
        });
    });
</script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"
        integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz"
        crossorigin="anonymous"></script>
<script src="{% static 'js/bootstrap.bundle.min.js' %}"></script>
<script src="{% static 'js/UrsusScripts.js' %}"></script>
<script src="{% static 'js/htmx.min.js' %}"></script>
</body>
</html>

I’d say the first thing you ought to try would be to move the loading of htmx to the top of the page header.

But you also still want to confirm that htmx itself is being loaded by the browser.

I moved it to the very top of the section but it didn’t make a difference.

Thanks

Top of which section?

It should be in the <head> element.

Quoting directly from the docs at </> htmx ~ Documentation

Htmx is a dependency-free, browser-oriented javascript library. This means that using it is as simple as adding a <script> tag to your document head. There is no need for a build system to use it.

Yes, that’s where I have it now, and I had it there originally. Doesn’t seem to make a difference though.

Is there any errors on the console tab of your browser?
Do you see an log entry on your runserverconsole window for a GET request to the htmx.min file?

I checked the console and there are no errors.

Thanks

What about the second question? This is the confirmation that the browser is issuing the GET request for the static file.

I see nothing in the console except some text that I am sending to the console from the UrsusScripts.js file.

For clarity, we’re talking about confirmation from three different locations:

  • Your runserver console, which shows the requests that have been submitted from the browser.

  • The “Network” tab in your browser’s developer tools showing that the request has been made by the browser to the server.

  • The “Elements” tab in your browser’s developer tools showing that the code has been injected into the DOM.

I have attached captures of the Elements and Network console.


Okay, here’s where the part of me that should have gone into finish carpentry comes in!! I’m not sure what you mean by runserver console, unless you mean the Python run console. I can see that the application is running but I don’t see anything else. Can you elaborate on what you mean by that, and assume you are explaining this to a finish carpenter for the very first time :slightly_smiling_face:!

Thanks as always for all of your feedback and efforts to help me solve this!

Thats exactly it.
But from the prints you provided it seems that the request is actually being served correctly.

One thing that you might notice is that the request/response is being cached by your browser. Maybe that can be causing the issue. I would first, check if the response looks like the minified version of HTMX (if is not an empty file for example). And do a hard reset (with the devtools on the browser open, right click on the refresh button on your browser and then “clear cache and hard reload”).

After that, if there’s still a problem, I would double check the code to see if there are no syntax errors or anything.