How to update the UI with UJS form submissions?

I know UJS is on the way out and will be removed when TL 6 comes out, but how should it be done right now. With a fresh Rails 6 installation, whenever a UJS-enabled from submission fails to validate in the controller, nothing happens in the view. Flash messages or field errors don’t appear.

Do I really have to create a .js response and handle it manually from there? Or am I missing something crucial?

To work around this, I took the Turbolinks approach by replacing the body if one is given:

function live(selector, event, callback, context) {
  (context || document).addEventListener(event, function(e) {
    var found, el = e.target || e.srcElement
    while (el && el.matches && el !== context && !(found = el.matches(selector)))
      el = el.parentElement
    if (found) callback.call(el, e)
  })
}

function handleUjsForm(event) {
  if (event.detail[0].nodeType == 9) {
    document.body.innerHTML = event.detail[0].body.innerHTML
  } else if (event.detail[2].status >= 400) {
    location.reload(true)
  }
}

live('form[data-remote=true]', 'ajax:success', handleUjsForm)
live('form[data-remote=true]', 'ajax:error', handleUjsForm)

A bit hackish, but it works and plays nice with Turbolinks and Stimulus. Still, I’m wondering if there is a better way.

Unfortunately you are not missing anything. A .js response is required.

1 Like

There’s no proper way. Async form submissions are sadly ignored.

I use https://optimism.leastbad.com/ to get around it, made by a user here: @leastbad

1 Like

If you’re using turbolinks, you might benefit from using the turbolinks_render gem until the new libraries come out.

What it essentially does is it allows calls to render from controllers (like render ‘new’ when a model is not saved correctly) to issue a turbolinks replace action from the server with the entire page and the form with errors

1 Like

Ok, thanks for all your responses. Not very Rails-like to keep something that big hanging. :slight_smile:

For the time being my workaround works well. I’ll keep my eyes open until the new goods arrive.