In a view that displays a list of categories, there is a little part underneath that shows the "default" of these categories. When a user clicks there, it is replaced by a drop down form where they can select the new default. Upon submitting of the form, the two parts of the page - list of categories as well as lower part where the default is shown - shall be updated via turbo stream.
This works once. If I try to click the lower element for the second time, the whole page renders blank even though the network tab of the browser shows that something is arriving. I don't understand why that happens.
view (index page):
<%= turbo_frame_tag 'settings-content' do %>
<h3 class="heading4">Available book formats</h3>
<ul class="simple-list width-33" id="book-formats">
<%= render 'new_form_entry' %>
<%= turbo_frame_tag 'format-list' do %>
<%= render @book_formats %>
<% end %>
</ul>
<h3 class="heading4 margin-top-1 margin-bottom-50">Default Book Format</h3>
<ul class="simple-list width-25">
<li>
<%= turbo_frame_tag 'default-format' do %>
<%= render 'book_formats/set_default_form' %>
<% end %>
</li>
</ul>
<% end %>
controller (relevant two methods):
def set_default
@book_formats = BookFormat.all.order(:name)
end
def update_default
@new_default = BookFormat.find_by(name: book_format_params[:name])
@default_book_format.update(fallback: false)
@new_default.update(fallback: true)
@default_book_format = @new_default
@book_formats = BookFormat.all.order(:name)
end
update_default.turbo_stream.erb
<%= turbo_stream.replace 'format-list' do %>
<%= render @book_formats %>
<% end %>
<%= turbo_stream.replace 'default-format' do %>
<%= render 'book_formats/set_default_form' %>
<% end %>
I am sure I am missing a small piece somewhere?
turbo_frame_tag
helper renders a <turbo-frame> tag and the form:
<turbo-frame id="default-format">
<form>
<!-- ... -->
</form>
</turbo-frame>
turbo_stream.replace
will replace the target #default-format with the template, in this case it is just the form:
<turbo-stream action="replace" target="default-format">
<template>
<form>
<!-- ... -->
</form>
</template>
</turbo-stream>
Which means <turbo-frame> goes away:
<!-- target identified by id -->
<!-- v v -->
<turbo-frame id="default-format"></turbo-frame>
<!-- is replaced by -->
<form></form>
<!-- end result -->
<form></form>
There is no #default-format
for the stream to replace the second time.
turbo_stream.update
action keeps the target and only updates the contents.
<!-- target identified by id -->
<!-- v v -->
<turbo-frame id="default-format"></turbo-frame>
<!-- target content is updated with -->
<form></form>
<!-- end result -->
<turbo-frame id="default-format">
<form></form>
</turbo-frame>
The target of the turbo-stream can be anything, not just turbo-frame:
<!-- unless you're doing something else with this frame,
there is no need for it -->
<%= turbo_frame_tag "format-list" do %>
<%= render @book_formats %>
<% end %>
<!-- just an `id` is enough for turbo-stream -->
<div id="format-list">
<%= render @book_formats %>
</div>