Hotwire Discussion

Redirecting back to proper page after form redirect

I am using will_paginate in Rails. To leverage Turbo Frames I have put the entire pagination area into a Turbo Frame. So selecting page 3 changes the tag to:

<turbo-frame id="mainframe" src="http://localhost:3000/packages/vlc?page=3">

So far so good. The URL shown to the user does not change but I can freely switch between pages.

I also want to allow the users to edit data. Imagine that a form on the third page is submitted through turbo. The form looks like:

<turbo-frame id="screenshot_19519" src="http://localhost:3000/packages/vlc/screenshots/19519/edit">
    <form action="/packages/vlc/screenshots/19519" accept-charset="UTF-8" method="post">
      <input type="hidden" name="_method" value="patch">
      <input type="text" name="screenshot[description]">
      <button class="button success" type="submit">
    </form>
</turbo-frame>

The form submits the changes properly. However I am not sure how to properly redirect back to page 3. Do I need to add the page number as a hidden field in the form and use that to find out which page the user was on? I hope there is a nicer way to actually redirect back to where the user actually came from.

Thanks in advance for any hints.

Have you tried redirect_back_or_to?

Thanks. Good idea. However I just read that this method takes the ‘Referer’ header and redirects back there. I have checked the headers:

  • I am on page 3.
  • Browser shows URL: http://localhost:3000/packages/vlc
    (because the change happened through Turbo and did not change the entire page)
  • Turbo frame that contains the paginated part: <turbo-frame id="mainframe" src="http://localhost:3000/packages/vlc?page=3">

So Turbo still has the “page=3” parameter in the ‘src’ attribute.

I click the button and get taken to the form target: http://localhost:3000/packages/vlc/hide_screenshot/4835

At this point the page number is already lost. And the referer is:

Referer: http://localhost:3000/packages/vlc

So I assume that Turbo takes the referer as shown in the browser URL field and not the “src” of the turbo-frame.

I could add a hidden field with the proper URL to redirect back to. However now that you mention the ‘Referer’ field I wonder if Turbo should change the Referer to reflect the “src” attribute. Should I add an issue on Github? Or am I just doing something wrong?

I think this should Just Work. The referrer header comes from the request, it’s nothing to do with the browser URL, which, as you say, is different in your case. This has always worked ok for me. Maybe the issue is the ?page query param. I’d try poking at the request through dev tools and seeing what you get.

I’m not sure I understand. Do you have a turbo-frame inside a turbo-frame?

<turbo-frame id="mainframe" src="http://localhost:3000/packages/vlc?page=3">
  <turbo-frame id="screenshot_19519" src="http://localhost:3000/packages/vlc/screenshots/19519/edit">
    <form action="/packages/vlc/screenshots/19519" accept-charset="UTF-8" method="post">
      <input type="hidden" name="_method" value="patch">
      <input type="text" name="screenshot[description]">
      <button class="button success" type="submit">
    </form>
  </turbo-frame>
</turbo-frame>

I could add a hidden field with the proper URL to redirect back to.
Be careful with this solution. See: Unvalidated Redirects and Forwards - OWASP Cheat Sheet Series

I usually avoid adding redirect urls in PARAMS.

Yes, that’s correct. The larger part of the page is wrapped in a frame I call “mainframe”. That frame consists of further elements that each use dom_id() like “screenshot_19519”. As far as I understand the Hotwire/Turbo documentation that is not a problem.

I think I see what you are trying to say. The outer frame contains the page number but the inner frame does not. The paginator uses the outer frame. The form I’m using (for in-place editing) is using the inner frame.

I will try to avoid that kind of nesting and see if that helps.

You’re correct, you should not have any issues with nested Turbo-Frames. As you partially pointed out, if the outer frame contains the pagination URL and the inner frame contains a sub element and form, after save why do you need to redirect the outer frame? Would it work for your scenario to just update the contents of the sub element frame?

Just wanted to get back and thank you both for your feedback. Turbo Frames indeed does the right thing. I just didn’t use the page number properly in the URL so it didn’t know where to redirect back to. You helped me figure that out.