[LRUG] Turbo - form render on error, redirect on success
Simon Fish
si at mon.fish
Thu Jan 27 11:12:00 PST 2022
Hey Andy,
I've got an issue open on hotwired/turbo for this purpose. There are solutions there, but they aren't super intuitive. https://github.com/hotwired/turbo/issues/138
I'm gonna come out and say that this is something Turbo should support out of the box. I think due to the way Turbo is architected that this isn't immediately possible, so it's sort of a shame things have to be this way... Feel free to get in touch if you've got any more Turbo questions - I've been running it in production since its release back at the end of 2020.
Thanks,
Simon
On Thu, Jan 27, 2022, at 3:18 PM, Andrew Stewart wrote:
> Hello LRUG!
>
> I'm upgrading a Rails 6.1 app to Rails 7 and am stuck on a straightforward problem. Hopefully I've just overlooked something obvious which a fresh pair of eyes will spot immediately :)
>
> So I have a Thing model. On the things index page there is a list of things and a new-thing form in a hidden modal at the bottom of the page. When the user clicks an "Add thing" button the modal opens.
>
> The behaviour I want is:
>
> - when the user submits an invalid form, the form re-renders in the modal with error messages etc;
> - when the user submits a valid form, the index page is reloaded – thus clearing away the modal with the filled-in form, showing the newly created thing in the list, and having a fresh new-thing form in a hidden modal.
>
> Unfortunately I'm able to achieve one or the other, but not both.
>
> This pattern of render on error, redirect on success was an issue for a while when Stimulus first came out, and then Turbo, but I thought it was all fixed up now. Unfortunately searching online mainly yields a gazillion workarounds and hacks from the early days which don't apply any more.
>
> Here's the (pseudo-)code:
>
>
> # things index page
>
> <!-- The data attributes are for a Stimulus controller which handles opening/closing modals -->
> = link_to '#', data: {controller: 'modal', action: 'modal#open', modal_id_param: 'thing-form'} do
> Add a new thing
>
> [ list of things ]
>
> <div id="thing-form" class="modal" ...modal attributes...>
> ...modal markup...
>
> = render partial: 'new', locals: {thing: Thing.new}
> </div>
>
>
> # new thing partial
>
> = turbo_frame_tag 'thing' do
> = form_with model: thing, id: dom_id(thing) do |f|
> ...input fields...
>
>
> # new thing page
>
> = render partial: 'new', locals: {thing: @thing}
>
>
> # things controller
>
> def create
> thing = Thing.new thing_params
> if thing.save
> redirect_to things_path, status: :see_other
> else
> render :new, status: :unprocessable_entity # or we could render the _new partial and ditch the new page
> end
> end
>
>
> With the code above, an invalid form submission renders into the modal as required, but a successful form submission doesn't reload the index page. The controller correctly sends a 303 redirect, and Turbo sees it and issues a fresh fetch for the index page – but for some reason doesn't replace/merge the page body. I'm actually not sure what it does.
>
> I have also tried:
>
> - adding `target: '_top'` to the turbo frame;
> - adding `data-turbo-frame="_top"` to the form;
> - both of the above.
>
> I can get the results I want if I use turbo stream responses from the controller to "manually" alter the view. But that feels wrong – like hard-coding something which shouldn't be hard-coded – and would require custom turbo stream responses everywhere else I use a form in a modal. Also this is a completely standard pattern and I believe that Turbo Drive / Frames should handle it without knowing details of the view.
>
> Any suggestions would be much appreciated!
>
> Many thanks,
>
> Andy Stewart
> _______________________________________________
> Chat mailing list
> Chat at lists.lrug.org
> Archives: http://lists.lrug.org/pipermail/chat-lrug.org
> Manage your subscription: http://lists.lrug.org/options.cgi/chat-lrug.org
> List info: http://lists.lrug.org/listinfo.cgi/chat-lrug.org
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.lrug.org/pipermail/chat-lrug.org/attachments/20220127/e0774d5b/attachment.html>
More information about the Chat
mailing list