TurboStream can't append new records to my index view

Hello! I’m just starting with Hotwire/Turbostreams, with some of the simplest examples I could think of.

I thought I’d take an Index page for my Engines model (using partials for each record), then put an Engine form at the top of it, and when you submit the form, I would use a Turbostream to simply append the new record to the Index’s list of records without a page reload.

It seemed easy enough but I can’t make it work! I keep getting the following log error (500 internal server), which seems to think my _engine partial is not getting an engine variable from the turbo stream.

"ActionView::Template::Error (undefined local variable or method `engine’ for #ActionView::Base:0x007fd57f100750
Did you mean? @engine):
1: <%= turbo_frame_tag(dom_id(engine)) do %>
2: …

Also, after the submit, the form on the index page disappears, so all that’s left on the page is the list of records. The new record does NOT appear (until you refresh the page), and the form partial at the top of the page DISAPPEARS. That’s a little strange that an unrelated element would disappear…

Anyway, here is my Create controller, which features the Turbo_stream response, which targets a div in my Index with an ID of “my_engines”. And no turbo_stream action works…not replace, prepend, etc.

  def create
    @engine = Engine.new(engine_params)

    respond_to do |format|
      if @engine.save
        format.turbo_stream { render turbo_stream: turbo_stream.append('my_engines', partial: 'engine'), locals: { engine: @engine } }
      else
        format.html { render :new, status: :unprocessable_entity }
      end
    end
  end

In case it’s helpful, here are abbreviated versions of my Index page and my _engine partial…note that each partial is wrapped in a TurboFrame tag, as I was also experimenting with those (ie, you can click the edit link for each record, and an in-line form appears).

<h1>Engines</h1>
<%= render 'engines/form', engine: @engine %>
<div id="my_engines">
  <% @engines.each do |engine|%>
    <%= render 'engine', engine: engine%>
  <% end %>
</div>
<br>

<%= turbo_frame_tag(dom_id(engine)) do %>
  <div class="flex p-2 mb-4 space-x-4 bg-gray-200 border">
    <p>
      <strong>Number:</strong>
      <%= engine.number %>
    </p>
    <%= link_to :show, engine_path(engine) %>
    <%= link_to :edit, edit_engine_path(engine) %>
    <%= link_to 'delete', engine, data: { turbo_method: 'delete', confirm: 'Are you sure?'  }%>
  </div>
<% end%>

Any thoughts are appreciated, THANKS VERY MUCH!

-H

1 Like

To me it looks like your locals parameter is not in the correct place

- format.turbo_stream { render turbo_stream: turbo_stream.append('my_engines', partial: 'engine'), locals: { engine: @engine } }
+ format.turbo_stream { render turbo_stream: turbo_stream.append('my_engines', partial: 'engine', locals: { engine: @engine }) }
2 Likes

Tieish, thanks very much for the reply! I noticed the same thing about 5 minutes after I submitted the post, and then thought I deleted the post so as to not waste anyone’s time.
But you’re right…I had my local outside the parenthesis, and that was the problem. I’m not sure how I missed that, but there it is…

Anyway, thanks again for taking a look and replying, it’s appreciated.

Starting to learn hotwire here. Thanks for the question., i dont need to repeat myself. Same scenario for me, the only difference is that the index file is a table. The table is made up by divs. The row not being added automatically. Its only after refresh that i see the new record. The turbo frame tag now is currently for the
for the whole table.

I need please some suggestions. Thanks