Rails Turbo Stream Before Action

Viewed 466

I'm trying out Turbo and Rails 7. Having a problem understanding where and how one would use the before action which Hotwire references:

<turbo-stream action="before" target="dom_id">
  <template>
    Content to place before the element designated with the dom_id.
  </template>
</turbo-stream>

I am using the example from the Hotwire website.

show.html.erb:

<p style="color: green"><%= notice %></p>

<%= turbo_stream_from @room %>

<%= turbo_frame_tag "room" do %>
  <%= render @room %>

  <div>
    <%= link_to "Edit this room", edit_room_path(@room) %> |
    <%= link_to "Back to rooms", rooms_path, "data-turbo-frame": "_top" %>

    <%= button_to "Destroy this room", @room, method: :delete %>
  </div>
<% end %>

<div id="messages">
  <%= render @room.messages %>
</div>

<%= turbo_frame_tag "new_message", src: new_room_message_path(@room), target: "_top" %>

_message.html.erb

<p id="<%= dom_id message %>">
    <%= message.created_at.to_s(:short) %>: <%= message.content %>
</p>

new.html.erb

<h1>New message</h1>

<%= turbo_frame_tag "new_message", target: "_top" do %>
  <%= form_with(model: [ @message.room, @message ],
      data: { controller: "reset-form", action: "turbo:submit-end->reset-form#reset" }) do |form| %>
    <div class="field">
      <%= form.text_field :content %>
      <%= form.submit "Send" %>
    </div>
  <% end %>
<% end %>

<%= link_to "Back", @message.room %>

create.turbo_stream.erb

<%= turbo_stream.append "messages", @message %>

How would one use the before action to insert the new message at the top of the list?

1 Answers

To insert messages at the top of the list you should use the prepend instead of the append action. This would add the content of <turbo-stream> as the first child of <div id="messages">.

# prepend
<div id="messages">
  ... new message ...
  ... old messages ...
</div>

# append
<div id="messages">
  ... old messages ...
  ... new message ...
</div>

The before and after actions however are used to add something outside of the the specified element. Either before or after it.

# before
... new message ...
<div id="messages">
  ... old messages ...
</div>

# after
<div id="messages">
  ... old messages ...
</div>
... new message ...

See the docs.

Related