5

I am creating a very basic Django messaging application, and would like to use htmx to send and render messages. I am able to post, save the message, and render the partial message without issue. However, I am running into a weird problem where my form textarea is not being reset. So, I would send a message, and after the swap is inserted, my old message would still be in the textarea. This isn't very ideal!

I tried to manually clear the textarea by adding an onclick event like so:

Html

<div id="new-message-div"></div>


<form id="message-form" class="chat-form rounded-pill bg-dark" data-emoji-form="" hx-post="{% url "chat:create-message" object.pk %}" hx-target="#new-message-div">
...

{{ message_form }}

...

<button class="btn btn-icon btn-primary rounded-circle ms-5" type="submit" onclick="submitForm()"> </button>
</form>

Script (https://stackoverflow.com/a/14589251/12758446)

<script>
function submitForm() {
   var message_form = document.getElementById('message-form');
   message_form.submit(); // Submit the form
   message_form.reset();  // Reset all form data
   return false; // Prevent page refresh
}
</script>

Despite having the message_form.submit() in the submitForm(), my form is not being submitted, but the textarea is getting reset.

Question:

How would I go about getting my textarea reset after successfully sending and rendering a message?

Django view, based off of https://github.com/legionscript/socialnetwork/blob/84375841429887e394a2a31e1b67919f81a3cb06/social/views.py#L428

def create_message(request, pk):
    message = None

    if request.htmx:
        thread = get_object_or_404(ThreadMessageModel, pk=pk)
        form = MessageModelForm(request.POST)

        if thread.receiver == request.user:
            receiver = thread.user
        else:
            receiver = thread.receiver

        if form.is_valid():
            message = form.save(commit=False)
            message.thread = thread
            message.sender_user = request.user
            message.receiver_user = receiver
            message.save()

        form = MessageModelForm()

        return render(request, 'chat/subtemplate/render_message.html', {'message': message})

3 Answers3

4

This also works:

<form hx-put="/" hx-on::after-request="this.reset()">
...
</form>

Discussion here: https://github.com/bigskysoftware/htmx/pull/1636

Jake Spracher
  • 805
  • 7
  • 10
2

In an attempt to generalise this behaviour in keeping with htmx’s declarative style, I’ve opted for an extension like this:

htmx.defineExtension('reset-on-success', {
    onEvent: function(name, event) {
        if (name !== 'htmx:beforeSwap') return;
        if (event.detail.isError) return;

        const triggeringElt = event.detail.requestConfig.elt;
        if (!triggeringElt.closest('[hx-reset-on-success]') && !triggeringElt.closest('[data-hx-reset-on-success]'))
            return;

        switch (triggeringElt.tagName) {
            case 'INPUT':
            case 'TEXTAREA':
                triggeringElt.value = triggeringElt.defaultValue;
                break;
            case 'SELECT':
                //too much work
                break;
            case 'FORM':
                triggeringElt.reset();
                break;
        }
    }
});

Now any form or input you tag with the attribute hx-reset-on-success will be reset after triggering a successful htmx request.

Usage is simple:

<body hx-ext="reset-on-success">
    <form method="POST"
          hx-post="/addtweet"
          hx-target="#timeline"
          hx-swap="afterbegin"
          hx-reset-on-success>
        <textarea name="tweet" rows="3" placeholder="What’s happening?"></textarea>
        <button type="submit">Send tweet</button>
    </form>
</body>

Could obviously be generalised further to somehow catch all inputs included in a request etc…

BenderBoy
  • 346
  • 2
  • 8
1

For server-side solutions you could:

  1. Increase the target in hx-target to include both the new message and the form so both are replaced on submit. Of course the response partial in this case would need to be adjusted.

  2. Keep things as they are now, but include the form in your response for an oob (out-of-band) swap https://htmx.org/attributes/hx-swap-oob/. For the oob swap, append the form markup to your new message response with the attribute hx-swap-oob="true".

Alejandro
  • 886
  • 5
  • 5