Search code examples
alpine.jshtmx

Alpinejs with HTMX prevents form submit on @click event


Using Alpinejs and HTMX both together.

There is a form that is submitted using HTMX on the form submit event, but I also want to show a spinner on the button and disable the button when the form is submitted.

<div class="" x-data="{submitted: false, submit() {this.submitted = true}}">
  <div class="card card-auth">
    <div class="card-header pb-0 text-start">
      <h4 class="font-weight-bolder">Authenticate</h4>
    </div>
    <div class="card-body">
      <form x-ref="authForm" role="form" hx-post hx-swap-oob="true" hx-target-error="#authentication_password">
        {% csrf_token %}
        
        {% include "components/input.html" with form=form name="email" label="Email" placeholder="Email" %}
        
         <div id="authentication_password"></div>

         <div class="text-center">
           <button @click="submit()" type="submit" class="" :disabled="submitted">
             Authenticate
             <i x-show="submitted" class="fa-solid fa-spinner fa-spin ms-2"></i>
           </button>
         </div>
       
       </form>
     </div>
   </div>
</div>

With this implementation, when a click happens, the spinner is displayed and the button is disabled, but the form is never submitted.

I tried adding

@click="submit(); $refs.authForm.submit()"

to manually refer the form element and triggers submit, but with this, HTMX is not submitting the form, instead the form is submitted using GET method and page refreshes.

I want @click to only set the submitted value but do not block further events.


Solution

  • The problem is caused by the disabled attribute of the button: when the disabled attribute is set to a submit button, the submit of the form is prevented by default.

    A simple solution can be to delay the disabled state using Alpine's $nextTick() magic method:

    <div class="" x-data="{submitted: false, submit() {$nextTick (() => this.submitted = true);}}">