Web developer & teacher @saaslit
The simplest turbo-frame example
Turbo frame is a powerful feature of Hotwire, here is a quick memo about how to follow conventions in the simplest case. Convention over configuration is powerful, but sometimes it is also a problem when you are not sure anymore about conventions ;) so I plan to release more "simplest *** Hotwire feature".
What is a turbo frame ?
A turbo frame is a node of the DOM that is able to be replaced by another, without refreshing the browser (when the user clicks on a button for example).
Think about the old days where you had to update the DOM through an ajax request (without a full page reload).
Unexplained (but short) answer
For those who already knows a little about Rails and Hotwire, and just want a quick check about syntax, here is the full (unexplained) answer :
# inside config/routes.rb
post "full_list", to: "welcome#full_list"
# inside app/controllers/welcome_controller.rb
class WelcomeController < DashboardController
def full_list
end
end
<!-- inside app/views/welcome/index.html.erb -->
<turbo-frame id="view_more">
<%= button_to "View all", full_list_path %>
</turbo-frame>
<!-- inside app/views/welcome/full_list.html.erb -->
<turbo-frame id="view_more">
<p>
That's all! Nothing else to show.
</p>
</turbo-frame>
A little bit of context
Rails is well known for it's "convention over configuration" paradigm. With simpler words, it means "as long as you follow naming conventions, everything works".
When discovering new features like Turbo and Hotwire, "everything works" usually starts by "everything is buggy"
So I decided to put this article as a reference for people who begins with Turbo Frame.
The bare minimum conventions not be off the Rails.
Prerequisites
ruby -v # 3.3.0
rails -v # 7.1.3
bundle -v # 2.4.10
node -v # 20.9.0
git --version # 2.34.1
Before turbo frames
As (every Monday actually;), build the bare minimum files to play with Rails, by creating a route, an associated controller, and a view :
rails new myapp
cd myapp
Then
# Create a default controller
echo "class WelcomeController < ApplicationController" > app/controllers/welcome_controller.rb
echo "end" >> app/controllers/welcome_controller.rb
# Create a default route
echo "Rails.application.routes.draw do" > config/routes.rb
echo ' get "welcome/index"' >> config/routes.rb
echo ' root to: "welcome#index"' >> config/routes.rb
echo 'end' >> config/routes.rb
# Create a default view
mkdir app/views/welcome
echo '<h1>turbo_frame tutorial</h1>' > app/views/welcome/index.html.erb
Then create database,
bin/rails db:create db:migrate
Then launch your local Rails server by typing :
bin/rails server
You should see the title "turbo_frame tutorial" when opening your browser at localhost:3000
Minimalistic turbo_frame
Actually, there is a simpler example, that directly loads the content of a frame from a source.
But I didn't had the use case so far, so I'll show an example where the turbo_frame is shown after a button has been clicked.
More realistic and simple turbo_frame
Controller and route has nothing special, it's plain old Rails.
# inside config/routes.rb
# add this line, below Rails.application.routes.draw do
post "full_list", to: "welcome#full_list"
# inside app/controllers/welcome_controller.rb
class WelcomeController < DashboardController
def full_list
end
end
There is nothing special to do in the controller when using turbo_frame
Now the interesting part
<!-- inside app/views/welcome/index.html.erb -->
<!-- add these lines below the h1 title -->
<turbo-frame id="view_more">
<%= button_to "View all", full_list_path %>
</turbo-frame>
Notice that the turbo-frame element is a HTML custom element.
It's coming from Turbo, so you don't have to define it yourself.
Use
<turbo-frame id="">
and not<div id="">
if you want frames to update your DOM.
<!-- inside inside app/views/welcome/full_list.html.erb -->
<turbo-frame id="view_more">
<p>
That's all!
</p>
</turbo-frame>
Use
.html.erb
extension, and not turbo_stream.html.erbUse the exact same
<turbo-frame> id
inside the returned partial.
To sum up,
All you have to do is to take care about file and folder naming conventions, and Rails will take care about updating the right element of the DOM.
Checking the code
Relaunch your local web server, and refresh the browser at localhost:3000
When you click the button, you should see "That's all", instead of the button. If this doesn't work, you probably missed something in the above steps :)
Don't forget to check the network request inside the web developer tools of the browser, in order to grab what is going on.
Summary
Turbo frame is some kind of weird name, for a very old and simple concept : update the DOM after a user action.
When following convention properly, Rails handles this for you very nicely :)