Hotwire Discussion

Turbo-frame won't update after a form submission

My understanding is that when turbo processes a request, it looks for turbo-frame elements in the current body that match turbo-frame elements in the response, and then swaps them out. I can make this work with links, but I’m not able to update turbo-frame elements from the response to a form submission.

I can also use turbo streams to individually update different parts of the page, but I’m hoping to avoid that. Can anyone help?

class WidgetsController < ApplicationController

	def create
		# doesn't work
		render 'index' 

		# neither does this:
		# redirect_to widgets_path, status: 303
	end

	def index
	end

end

Here’s the view:

= turbo_frame_tag 'number' do
	h1 = rand

// this works as expected
= link_to 'Update', widgets_path

// this doesn't
= form_with url: widgets_path, method: :post do
	= submit_tag 'Update (form)'

// neither does this
= button_to widgets_path, method: :post do
	| Update (button_to)

and the logs:

// rendering a template in the response
Started POST "/widgets" for 127.0.0.1 at 2021-09-10 13:02:59 +0100
Processing by WidgetsController#create as TURBO_STREAM
  Parameters: {"authenticity_token"=>"[FILTERED]"}
  Rendering widgets/index.slim
  Rendered widgets/index.slim (Duration: 0.6ms | Allocations: 293)
Completed 200 OK in 2ms (Views: 1.2ms | Allocations: 791)

// redirecting in the response
Started POST "/widgets" for 127.0.0.1 at 2021-09-10 13:31:01 +0100
Processing by WidgetsController#create as TURBO_STREAM
  Parameters: {"authenticity_token"=>"[FILTERED]"}
Redirected to http://localhost:3000/widgets
Completed 303 See Other in 2ms (Allocations: 417)


Started GET "/widgets" for 127.0.0.1 at 2021-09-10 13:31:01 +0100
Processing by WidgetsController#index as TURBO_STREAM
  Rendering widgets/index.slim
  Rendered widgets/index.slim (Duration: 1.7ms | Allocations: 457)
Completed 200 OK in 4ms (Views: 3.3ms | Allocations: 982)

Are you still using Rails UJS? If so, you may need ensure your form is submitted locally:
<%= form_with ... local: true do |f| %>

Hi, no I removed that

I think it’s something to do with slim. I tried an example using erb templates and it worked as expected. I diff’d the output to compare the markup that slim generates vs erb and they look identical. However, the browser network tab shows that when rendered using slim, the form submission doesn’t request any js files, but when rendered using erb it does.

Update: it was the filename. index.slim doesn’t work. index.html.slim works as expected.

1 Like