How does LiveView know when to remove phx-disable-with from form submits?

When submitting a form, LiveView toggles into the phx-disable-with state. Then it removes the phx-disable-with while my server’s handler is in the process of executing the phx-submit="..." handler.

What triggers the removal of that phx-disable-with? Is there any way to prevent this from happening until after my submit handler has finished? On a slow connection, my app toggles into the loading state while submitting the form as desired, but then removes this state and appears broken/waiting while my handler runs.

Thanks!

From this link the form should be restored only after the submit has finished.

On submission of a form bound with a phx-submit event:

  1. The form’s inputs are set to readonly
  2. Any submit button on the form is disabled
  3. The form receives the "phx-submit-loading" class

On completion of server processing of the phx-submit event:

  1. The submitted form is reactivated and loses the "phx-submit-loading" class
  2. The last input with focus is restored (unless another input has received focus)
  3. Updates are patched to the DOM as usual

What does the log show?
Are you doing something heavy in the server that would be better handled by async tasks?
Have you tried enabling livesocket debug and checking the console for errors? Maybe a timeout?

window.liveSocket = liveSocket

// in the browser's web console
liveSocket.enableDebug()

Without more info is hard to know for sure, but if it is some kind of timeout due to heavy work my suggestion would be to make everything as light as possible for the user and do the heavy work outside the main codepath.

Hrm, ok. It’s definitely network-related, not due to any work I’m doing server-side. This happens with the vanilla code from the generators. If I set the latency to five seconds, there’s a delay with the loading indicator, then a delay without the loading indicator before the form is closed and the page navigation occurs. The flash message at the end the save handler isn’t shown until the end of the second delay, making me think that the loading indicator is hidden before the response from the submit.

I’ve bootstrapped a new LiveView app that demonstrates this, but haven’t deployed it anywhere yet: GitHub - dfalling/latency_demo: Demo of latency effects in LiveView

Here’s a gif of the behavior in action:

2024-02-01 07.56.56

Note how the redirect and flash are both after the second delay.

I see, unfortunately it is happening as intended since the form is re-enabled after the submit is successful and what is taking a while to happen is the push_patch which is another operation unrelated to the form.

Changing push_patch to push_navigate helps a little but doesn’t fix the problem at all if the latency is bad enough.

My take if I have control over this decision is that I would get rid of modals for forms because 99% of the time they are bad UX, but if I can’t change it I would probably control the form manually to handle these latency issues…

But I can see how this would be at least a bug in the generators because if the person keeps clicking on submit it will create duplicate items, so you probably should open an issue.

Exactly. That’s why I was hoping there’s a way to replicate or prevent the dismissal of the default saving logic. It works great for the first half of the save, and I’d rather not have to handle the second half in a different manner.

One workaround would be to add a phx-click={JS.show(to: "saving-indicator")} to my form’s submit button. Then I just have to remember to add a JS.hide in my submit handler’s failure branch.

But again, I’d love a way to leverage the existing logic somehow.