Home > Net >  Turbo stream in Rails
Turbo stream in Rails

Time:12-17

So, I have a turbo frame in the show view of my Rental:

views/rentals/show.html.erb

<%= turbo_frame_tag "new_rate", src: new_rental_rate_path(@rental) %>
<div id="rates<%= year %>">
 <%= render @rates.where("DATE_PART('year', firstnight) = ?", year) %>
</div>

views/rates/new.html.erb

<%= turbo_frame_tag "new_rate", do %>
  <%= render "form", rate: @rate, vrental: @vrental %>
<% end %>

views/rates/form.html.erb

<%= simple_form_for [vrental, rate], id: dom_id(rate, "form") do |f| %>

controllers/rates_controller.rb

  def create
    @rate = Rate.new(rate_params)
    @rate.rental = @rental

    if @rate.save
      flash.now[:notice] = "You've created a new rate."
      render turbo_stream: [
        turbo_stream.prepend("rates#{@rate.firstnight.year}", @rate),
        turbo_stream.replace("new_rate", partial: "form", locals: { rate: Rate.new }),
        turbo_stream.replace("notice", partial: "shared/flashes"),
      ]
    else
      render :new, status: :unprocessable_entity
    end
  end

So, here's the problem.

On page load, the new rate form is correctly rendered inside a turbo frame:

<turbo-frame id="new_rate" src="http://localhost:3000/rentals/1/rates/new" complete="">
  <form id="new_rate" [...]>
  </form>
</turbo-frame>

However, after submitting and correctly saving the first rate, the form is then displayed outside the turbo frame:

  <form id="new_rate" [...]>
  </form>

I can see that it's happening because I'm replacing the div with "new form" id by partial: "form", which is not wrapped in a turbo frame, but I can't figure out how to fix it..

CodePudding user response:

The most simplistic solve for this is to add a partial that loads the form. but to keep it DRY, make sure to render that partial from within your new.html.erb file.

Practically, it will look like this.

views/rates/new.html.erb

<%= render "new" %>

views/rates/_new.html.erb

<%= turbo_frame_tag "new_rate", do %>
  <%= render "form", rate: @rate, vrental: @vrental %>
<% end %>

app/controllers/rates_controller.rb

def create
  @rate = Rate.new(rate_params)
  @rate.rental = @rental

  if @rate.save
    flash.now[:notice] = "You've created a new rate."
    render turbo_stream: [
      turbo_stream.prepend("rates#{@rate.firstnight.year}", @rate),
      turbo_stream.replace("new_rate", partial: "new", locals: { rate: Rate.new }),
      turbo_stream.replace("notice", partial: "shared/flashes"),
    ]
  else
    render :new, status: :unprocessable_entity
  end
end
  • Related