I'm simply trying to learn how to use Hotwire with Rails and having trouble with even a basic example.
All I want to do is have a button which refreshes the current time on the index page of my app. BUT! I want the button to be outside of the turbo frame. When the button is inside the turbo frame it works flawlessly, but I want the flexibility of having the button and frame be separate if I need it to be.
The following works fine:
index.html.haml
%h1 The current time is:
= turbo_frame_tag "time_frame" do
%span= @time
= button_to "Refresh Time", root_path, method: :get
But this doesn't:
index.html.haml
%h1 The current time is:
= turbo_frame_tag "time_frame" do
%span= @time
%div
= button_to "Refresh Time", root_path, method: :get, remote: true, data: { turbo_frame: "time_frame" }
MainController.rb
def index
@time = Time.zone.now
respond_to do |format|
format.turbo_stream do
render(turbo_stream: turbo_stream.replace("time_frame", partial: "time_partial"))
end
format.html
end
end
_time_partial.html.haml
%span= @time
When the button is pressed, I can see that the response comes from the server with the body like so:
<turbo-stream action="replace" target="time_frame"><template><span>2025-07-31 15:43:45 -0700</span>
</template></turbo-stream>
The content-type
of the response is "text/vnd.turbo-stream.html; charset=utf-8"
There are not errors in either the frontend or backend.
But the time shown on the page does not change.
What am I doing wrong?
I found the solution. The button needs to be inside its own turbo frame tag in order to function properly. But I can specify the target frame id so that the value of the current time is replaced. Otherwise the frame that has the button will be reloaded (with nothing changed).
%h1 The current time is:
= turbo_frame_tag "time_frame" do
%span= Time.zone.now
= turbo_frame_tag "something_else" do
= button_to "Refresh Time", root_path, method: :get, data: { turbo_frame: "time_frame" }
With this change, the time updates on button click without refreshing the page. This also works without any of the format
code in the controller or the additional partial.
The response on clicking the button is now text/html
instead of text/vnd.turbo-stream.html