See Hotwire handbook
- Update hotwired/turbo-rails
- Remove rails/ujs
- Replace link_to delete
- Replace link_to data confirm
- Replace button data disable with
- Set status response in controller
1. Update hotwired/turbo-rails
In package.json, update @hotwired/turbo-rails
package to 7.1.0 (or greater)
"@hotwired/turbo-rails": "^7.1.0"
2. Remove rails/ujs
- From the package.json file
yarn remove @rails/ujs
- From the application.js entry point
require("@rails/ujs").start() // remove this line
3. Replace link_to delete
method: :delete
becomes
data: {turbo_method: :delete}
<%# Old %>
<% link_to "Destroy", task_path(@task), method: :delete %>
<%# New %>
<% link_to "Destroy", task_path(@task), data: {turbo_method: :delete} %>
4. Replace link_to data confirm
data: {confirm: 'Are you sure?'}
becomes
data: {turbo_confirm: 'Are you sure?'}
<%# Old %>
<% link_to "Destroy", task_path(@task), method: :delete, data: {confirm: 'Are you sure?'} %>
<%# New %>
<% link_to "Destroy", task_path(@task), data: {turbo_method: :delete, turbo_confirm: 'Are you sure?'} %>
5. Replace button data disable with
In Rails UJS, a form's submit button can be disabled and its text replaced by adding the data disable_with attribute.
<%= f.button "Search", data: { disable_with: "Searching..."} %>
With Turbo, you can set the text content based on the parent's button disabled status. Source
button .show-when-disabled { display: none; }
button[disabled] .show-when-disabled { display: initial; }
button .show-when-enabled { display: initial; }
button[disabled .show-when-enabled { display: none; }
<button>
<span class="show-when-enabled">Submit</span>
<span class="show-when-disabled">Submitting...</span>
</button>
Or if you use Tailwind, you can leverage Tailwind's group and disabled status to create a similar effect.
<%= f.button class: "group" do %>
<span class="group-disabled:hidden">Search</span>
<span class="hidden group-disabled:block group-disabled:cursor-wait">Searching...</span>
<% end %>
6. Set status response in controller
Respond with a 303 status code
class TasksController
...
def destroy
@task = Task.find(params[:id])
@task.destroy
redirect_to tasks_path, info: "Task deleted", status: :see_other
end
end
Top comments (7)
Thank you!
Hi Thomas! I'm having issues with:
link_to, url, method: :get
. The link goes to a controller action that response with turbo_stream but the request arrives as HTML and I get an error after removing ujs. Tried addingdata-turbo-method="get"
but because my link is inside a turbo-frame it saysResponse has no matching <turbo-frame id="idOfRandomParent"> element
. Did you by any chance encounter such issues?@bakivernes, you can break out a
turbo_frame
by specifing the target attribute on a link.See also here
Excellent, that sums up what I also discovered.
Have you investigated the replacements for
Rails.fire
andRails.ajax
? Asking as these are the 2 next on my list.@fcatuhe, I'm glad you find it useful.
There is a recent rails library called Request.js which can fetch URL's in JS. This can help migrate existing Rails.fire and Rails.ajax calls.
Wow I had missed that one, that's exactly it, thanks!
very good write-up on removing ujs! thanks!