Ask A Question

Notifications

You’re not receiving notifications from this thread.

How to upgrade from Turbolinks to Hotwire & Turbo Discussion

Hey Chris, thanks for going over Turbo and StimulusJS 2.0 changes, I'm really excited about using them in my projects!

One really big thing that would be great to cover is using dialogs/modals with Turbo.

In several of my projects, users really like having dialogs/modals that can show information or allow them to edit information via forms without losing context in the app.

One issue with that, however, is that you can't bookmark or link to a "show" action dialog because it's displayed via JS. In my case, I can have multiple dialogs on top of each other, and each dialog is dynamically appended to the body, which is different from the approach of having a single <div id="dialog">...</div> hidden on the page and just updating content (because you can't have multiple).

With regards to dialogs and forms, I've gone the route of remote: true on all the forms and using create.js.erb to execute JS code on the client. As an example:

# posts_controller.rb
def create
  @post = Post.new(post_params)

  if @post.save
    # create.js.erb
  else
    render :form_validation_error # js.erb file
  end
end

# posts/create.js.erb
Dialog.hide("#new-post-form")
Snackbar.create("Post successfully created")

# posts/form_validation_error.js.erb
# Using jQuery syntax for example of what I'm doing
$("#new-post-form .dialog-content").replaceWith("<%=j render(partial: 'posts/form') %>")

I've been looking at Turbo with its turbo-forms and turbo-streams, and it looks like the core team is headed in a different direction, since they don't want to execute arbitrary JS as a response anymore and instead recommend StimulusJS callbacks (read that in one of the guides for either StimulusJS or Turbo, can't remember which).

But the core issue is making Turbo play nicely with multiple dialogs/modals on a page, some of them just showing info and some of them actually forms that submit data.

My current solutions "work", but it looks like I'll need to do a significant amount of refactoring to make them play nicely with the direction Turbo is going.

Reply

I am using the most recent versions of hotwire and turbo rails but when submitting a form (successfully) nothing happens. If there is an error it displays the error. Anyone an idea what could go wrong there?

Reply

Updating my Ruby version to 2.6.5 and updating turbo-rails to 0.5.3 resolved this issue for me.

Reply

I'm having the same issue...
ruby: 2.7.2
rails: 6.1
turbo-rails: 0.5.3 (7.0.0-beta.3)

I'm using the turbo_frame_tag 'report_form' wrapping the form and in the controller I have

def create
    @report = Report.new(report_params)
    respond_to do |format|
      if @report.save
        format.html { redirect_to @report, notice: "Report was successfully created" }
        format.json { render :show, status: :created, location: @report }
      else
        # format.turbo_stream { render turbo_stream: turbo_stream.replace(@report, partial: 'reports/form', locals: { report: @report })}
        format.html { render :new, status: :unprocessable_entity }
        format.json { render json: @report.errors, status: :unprocessable_entity }
      end
    end
  end

The commented line also works, in that case, the response for the error only renders the form partial, but I still have the same problem for the success... nothing happens.

Reply

I seem to have an issue getting successful submissions to work in this use case.

For example, I have a form like:

<%= turbo_frame_tag record do %>
  <%= form_with model: record, local: true) do |form| %>
    <%# ... %>
  <% end %>
<% end %>

If the controller action is:

def update
  if @record.update(record_params)
    redirect_to record, notice: 'Record was successfully updated!'
  else
    render :edit
  end
end

(Note that I don't have responders in my actions because I'm creating another separate JSON API, but maybe I need to create one for turbo streams now?)

I see the error messages as expected when there is a validation error, however I do not get redirected to the :show action when the form successfully submits. From looking here it kinda seems like this isn't supported, but it seems like the idiom up until now for Rails, so I'm not sure if I'm reading this correctly. Any tips?

Thanks!

Reply

For now I am simply removing the turbo_frame_tag and returning a status: :unprocessable_entity on error which causes Turbo to work in the success and error case, although it does re-render the whole page. It seems to work fine, although I am a bit curious if there's a more complete solution to this.

Reply

I just upgraded to Hotwire/Turbo today and am in the same situation. Still learning the ropes with Turbo, but it does seem wrapping forms with turbo frame tags in existing applications is generally not a workable solution.

Reply

Hi everyone, in application.html.erb, should our stylesheet and script pack tags be annotated with 'data-turbo-track': 'reload' or 'data-turbolinks-track': 'reload' after switching to hotwire/turbo?

Reply

I'm wondering if adopting Hotwire means the end of webpacker in my Rails application, as webpacker is pretty heavy lifting considering the scant js I use. So is it back to the asset pipeline and precompiling and all that? Maybe a tutorial on dismantling webpacker safely and installing hotwire in its place. There doesn't seem to be anyone clearly stating that webpacker is on the chopping block. Will you make that call, Chris?

Reply

Hotwire is not a replacement for Webpacker but there are other gems which could replace webpacker in your project, depending on how you're using it. https://gorails.com/episodes/esbuild-jsbundling-rails

Reply

This was very helpful. Thank you Chris.

Reply

Hi everyone!

I've managed to get forms working using status: :unprocessable_entity against my calls to render for error cases.

However, some of my form pages are long, and so while the flash messages are correctly displayed when the page re-renders, they are off screen at the top. With Turbolinks, the pages would naturally reload at the top of the page.

Anybody know the best way to handle this case?

Thank you!

Reply

Hello Nadia, I experienced a similar issue and the workaround I used was to scroll to the top of the page after the form submission :(

In my case, I did it with a Stimulus controller but it can be achieved with jQuery or vanilla JS.

Reply
Join the discussion
Create an account Log in

Want to stay up-to-date with Ruby on Rails?

Join 87,563+ developers who get early access to new tutorials, screencasts, articles, and more.

    We care about the protection of your data. Read our Privacy Policy.