This article is basically a snippet for a common pattern in web apps, and I struggle to find the right way each time I want to implement this behaviour in my rails apps with turbo enabled ๐
What we want
On a form submission, I want to redirect to a new page on success, and render errors otherwise.
Letโs take a dummy model for our example: a Post with title/description as text attributes
Without turbo
In plain old HTTP without js/javascript, the controller is pretty straightforward:
And our new.html.erb view:
When turbo is enabled, it does not work at all.
FYI, If you want to disable turbo you can add the data-turbo="false"
to
the form (which solved the issue).
With turbo
Like I said in the intro, I struggle each time to have a working version of this with turbo, which consists of a dynamic display of errors and a simple redirect to my path.
The process:
Wrap your form (with errors) in a turbo-frame
tag, and add a
turbo-frame="_top"
on the form:
The tricky part here is the turbo-frame="_top"
: without it turbo intercept
the redirection, and does not perform a โfullโ reload of our page.
In the controller, on success use http status 303 (See Other), and on failure use a 422 http status (Unprocessable entity)
Turbo relies a lot on HTTP status. When the server renders a 4xx or 5xx error, it does not perform the redirection.
At this point, it does not render errors yet. Thanks to this issue (and this comment), I managed to find a way to solve this.
All you need to do is to write a new.turbo_stream.erb
which weโll be triggered
by the render :new
in our controller:
When you submit your form, it accepts turbo stream as response, adding a view with turbo stream format bypass entirely the html response and let us to do what we want: render the form (and the errors) on our frame.
Note: You have to put your entire โnewโ view in a partial (or just your form) in order to be able to use a partial here.
At this point, it should be OK.