# Broadcasting to nested turbo\_frame\_tag

**URL:** <https://discuss.hotwired.dev/t/broadcasting-to-nested-turbo-frame-tag/3659>\
**Category:** General\
**Created:** [January 3, 2022, 5:59pm UTC](https://discuss.hotwired.dev/t/broadcasting-to-nested-turbo-frame-tag/3659 "2022-01-03T17:59:07Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![GuillaumeGrassiant](https://yyz1.discourse-cdn.com/flex027/user_avatar/discuss.hotwired.dev/guillaumegrassiant/32/2461_2.png) [@GuillaumeGrassiant](https://discuss.hotwired.dev/u/GuillaumeGrassiant)\
**Post date:** [January 3, 2022, 5:59pm UTC](https://discuss.hotwired.dev/t/broadcasting-to-nested-turbo-frame-tag/3659/1 "2022-01-03T17:59:07Z")

</div>

Hi everyone,  
I hope 2022 is off to a good start for you.

I have an issue similar to [this one](https://discuss.hotwired.dev/t/nested-frame-and-stream/1990) but for some reason, the solution does not seem to work in my case.

Basically, I am trying to get familiar with Hotwire and I want to create a blog that works like a single-page app (so turbo stream the crud to change the content of the `turbo_frame_tag` without reloading the page) but I also want to try out broadcasting both the `posts` and the `comments` in real-time.

The only thing not working is the broadcasting of the `comments`, broadcasting the `posts` work. I think it has to do with how I use the `turbo_stream_from`, `turbo_frame_tag` and/or the way I broadcast but I can’t seem to get it right.

My current `posts/index`

```auto
<%= turbo_stream_from "posts" %>

<div class="w-full">
  [...]
  <div class="min-w-full">
    <%= turbo_frame_tag :posts do %>
      <%= render @posts %>
    <% end %>
  </div>
</div>

```

he partial for each post is as follows:

```auto
<%= turbo_frame_tag post do %>
  <div class="bg-white w-full p-4 rounded-md mt-2">
    <h1 class="my-5 text-lg font-bold text-gray-700 text-4xl hover:text-blue-400">
      <%= link_to post.title, post_path(post) %>
    </h1>
   [...]
  </div>
<% end %>

```

the `posts/show` replaces the current partial of each post with a more detailed version:

```auto
<%= turbo_stream_from @post, :comments %>

<%= turbo_frame_tag dom_id(@post) do %>
  [...]
    <div class="w-full bg-white rounded-md p-4 justify-start mt-1">
      <div class="w-full pt-2">
        <turbo-frame id="total_comments" class="mt-2 text-lg text-2xl mt-2 tex-gray-50">
          <%= @post.comments.size %> comments
        </turbo-frame>
        <%= turbo_frame_tag "#{dom_id(@post)}_comments" do %>
          <%= render @post.comments %>
        <% end %>
        [...]
      </div>
    </div>
  </div>
<% end %>

```

with the respective models being:

```auto
class Post < ApplicationRecord
  validates_presence_of :title
  has_rich_text :content
  has_many :comments, dependent: :destroy
  after_create_commit { broadcast_prepend_to "posts" }
  after_update_commit { broadcast_replace_to "posts" }
  after_destroy_commit { broadcast_remove_to "posts" }
end

```

and

```auto
class Comment < ApplicationRecord
  include ActionView::RecordIdentifier

  belongs_to :post
  has_rich_text :content

  after_create_commit do
    broadcast_append_to [post, :comments], target: "#{dom_id(post)}_comments", partial: 'comments/comment'
  end

  after_destroy_commit do
    broadcast_remove_to self
  end
end

```

The `_comment` partial is

```auto
<%= turbo_frame_tag dom_id comment do %>
  <div class="container w-full mx-auto bg-white p-4 rounded-md mt-2 border-b shadow">
    <%= comment.content %> - <%= time_tag comment.created_at, "data-local": "time-ago" %>
    [...]
  </div>
<% end %>

```

Any idea what I am doing wrong?  
Thanks a lot in advance and have a great day.

---

<div class="post-metadata">

**Author:** ![rockwell](https://yyz1.discourse-cdn.com/flex027/user_avatar/discuss.hotwired.dev/rockwell/32/1884_2.png) [@rockwell](https://discuss.hotwired.dev/u/rockwell)\
**Post date:** [January 3, 2022, 7:38pm UTC](https://discuss.hotwired.dev/t/broadcasting-to-nested-turbo-frame-tag/3659/2 "2022-01-03T19:38:52Z")

</div>

Hey. Hoping 2022 is off to a good start for you too.

> [@GuillaumeGrassiant](#):
>
> ```auto
> after_create_commit do
> broadcast_append_to [post, :comments], target: "#{dom_id(post)}_comments", partial: 'comments/comment'
> end
> 
> ```

Have you tried

```ruby
  after_create_commit do
    broadcast_append_to post, :comments, target: "#{dom_id(post)}_comments", partial: 'comments/comment'
  end

```

---

<div class="post-metadata">

**Author:** ![GuillaumeGrassiant](https://yyz1.discourse-cdn.com/flex027/user_avatar/discuss.hotwired.dev/guillaumegrassiant/32/2461_2.png) [@GuillaumeGrassiant](https://discuss.hotwired.dev/u/GuillaumeGrassiant)\
**Post date:** [January 3, 2022, 8:35pm UTC](https://discuss.hotwired.dev/t/broadcasting-to-nested-turbo-frame-tag/3659/3 "2022-01-03T20:35:05Z")

</div>

Hi!  
Thanks a lot for your message 🙂

I just tried the snippet (the one without the brackets around `post` and `:comments`) but it still did not broadcast the new comment.

In the console, It does say something like:

```auto
  Rendered comments/_comment.html.erb (Duration: 1.8ms | Allocations: 877)
[ActionCable] Broadcasting to [...some string like Z2lk...]:comments: "<turbo-stream action=\"append\" target=\"post_1_comments\"><template><turbo-frame id=\"comment_39\">\n <div class=\"container w-full mx-auto bg-white p-4 rounded-md mt-2 border-b shadow\">\n <div class=\"trix-content\">\n <div>qwe</div>\n</div>\n - <time datetime=\"2022-01-03T20:26:29Z\" da...
  Rendering comments/create.turbo_stream.erb

```

---

<div class="post-metadata">

**Author:** ![rockwell](https://yyz1.discourse-cdn.com/flex027/user_avatar/discuss.hotwired.dev/rockwell/32/1884_2.png) [@rockwell](https://discuss.hotwired.dev/u/rockwell)\
**Post date:** [January 4, 2022, 7:47am UTC](https://discuss.hotwired.dev/t/broadcasting-to-nested-turbo-frame-tag/3659/4 "2022-01-04T07:47:21Z")

</div>

Are you returning a `turbo_stream` format?. Like in the controller do you have something like

```ruby
class CommentsController
   def create
    # create a comment
    respond_to do |format|
       format.turbo_stream { render :create }
   
    end
   end
end

```

if so, try removing the file `comments/create.turbo_stream.erb` or just rename it and see what it does. Like, don’t return a stream response when creating the comment. From my experince with streaming with Turbo. If you had a `somemodel/{action}.turbo_stream.erb` it will take presedence over the `after_create_commit` defined inside the model.

---

<div class="post-metadata">

**Author:** ![GuillaumeGrassiant](https://yyz1.discourse-cdn.com/flex027/user_avatar/discuss.hotwired.dev/guillaumegrassiant/32/2461_2.png) [@GuillaumeGrassiant](https://discuss.hotwired.dev/u/GuillaumeGrassiant)\
**Post date:** [January 4, 2022, 12:59pm UTC](https://discuss.hotwired.dev/t/broadcasting-to-nested-turbo-frame-tag/3659/5 "2022-01-04T12:59:22Z")

</div>

Hello!

I am indeed returning a stream format.

My `comments#create` is

```auto
 def create
    @comment = @post.comments.build(comments_params)

    respond_to do |format|
      if @comment.save
        format.turbo_stream
        format.html { redirect_to @post, notice: 'Comment was successfully created.' }
        format.json { render :show, status: :created, location: @comment }
      else
      [...error handling]
      end
    end
  end

```

with the partial `create.turbo_stream` itself being

```auto
<% if @comment.errors.present? %>

[...some error handling]

<% else %>
  <%= comment_notice_stream(message: :create, status: 'green') %> # a helper to display a notice

  <%= turbo_stream.replace 'new_comment' do %>
    <%= turbo_frame_tag :new_comment %>
  <% end %>

  <%= turbo_stream.append "#{dom_id(@post)}_comments", partial: 'comment', locals: { comment: @comment } %>

  <%= turbo_stream.replace 'total_comments' do %>
    <%= turbo_frame_tag :total_comments, class: 'mt-2 text-lg text-2xl mt-2 tex-gray-50' do %>
      <%= @post.comments.size %> comments
    <% end %>
  <% end %>
<% end %>

```

When I rename the `create.turbo_stream` file and/or comment out the `format.turbo_stream`, and then try creating a comment from a different browser window, the comment gets created but does not show on the page without a reload (which is kind of expected since I removed the `turbo_stream`) but does not appear on the other browser window either, where I would expect it to be broadcasted. This means that I am probably not broadcasting as I should.

I still get in the console `[ActionCable] Broadcasting to [...some string]:comments:.....`

Basically what I did is follow [this article](https://dev.to/nemuba/blog-demo-using-rails-7-hotwire-rails-tailwindcss-stimulus-railsrequestjs-2c7a) to get me started with a “spa-like” version of the blog and then tried to tweak it to add some actioncable/broadcasting for the posts/comments.

Thanks again for your help!

---

<div class="post-metadata">

**Author:** ![GuillaumeGrassiant](https://yyz1.discourse-cdn.com/flex027/user_avatar/discuss.hotwired.dev/guillaumegrassiant/32/2461_2.png) [@GuillaumeGrassiant](https://discuss.hotwired.dev/u/GuillaumeGrassiant)\
**Post date:** [January 5, 2022, 10:24pm UTC](https://discuss.hotwired.dev/t/broadcasting-to-nested-turbo-frame-tag/3659/6 "2022-01-05T22:24:25Z")

</div>

Hey!  
So I found a way to make it work.

In `posts/show`, it was a matter of putting the stream inside the turbo\_frame:

```auto
<%= turbo_frame_tag dom_id(@post) do %>
[...]
    <%= turbo_stream_from @post, :comments %>
    <div class="w-full bg-white rounded-md p-4 justify-start mt-1">
      <div class="w-full pt-2">
        <turbo-frame id="total_comments" class="mt-2 text-lg text-2xl mt-2 tex-gray-50">
          <%= @post.comments.size %> comments
        </turbo-frame>
        <%= turbo_frame_tag "#{dom_id(@post)}_comments" do %>
          <%= render @post.comments %>
        <% end %>

        <div class="w-full mb-5 mt-5">
        <%= turbo_frame_tag :new_comment %>
      </div>
      <%= link_to 'New Comment', new_post_comment_path(@post), data: { turbo_frame: 'new_comment' }, class: 'bg-blue-500 text-white text-center p-2 rounded-md' %>
      </div>
    </div>
[...]
<% end %>

```

That makes creating a comment work.

And to delete a comment in both windows I needed to add a stream at the beginning of the partial:

```auto
<%= turbo_stream_from comment %>
<%= turbo_frame_tag dom_id comment do %>
 [...content]
<% end %>

```

the only thing left to solve is how to update in both windows the count when broadcasting a new comment:

in `posts/show`:

```auto
        <turbo-frame id="total_comments" class="mt-2 text-lg text-2xl mt-2 tex-gray-50">
          <%= @post.comments.size %> comments
        </turbo-frame>

```

If you have any idea, let me know 🙂  
Have a good day.

---

<div class="post-metadata">

**Author:** ![rockwell](https://yyz1.discourse-cdn.com/flex027/user_avatar/discuss.hotwired.dev/rockwell/32/1884_2.png) [@rockwell](https://discuss.hotwired.dev/u/rockwell)\
**Post date:** [January 6, 2022, 7:28am UTC](https://discuss.hotwired.dev/t/broadcasting-to-nested-turbo-frame-tag/3659/7 "2022-01-06T07:28:57Z")

</div>

Hi. This is wonderful, you can define a partial that contains this

inside `posts/_comment_count.html.erb` or anywhere u would like to define the partial

```auto
        <turbo-frame id="total_comments" class="mt-2 text-lg text-2xl mt-2 tex-gray-50">
          <%= post.comments.size %> comments
        </turbo-frame>

```

Then, in the `after_create_commit` callback you can stream that specific partial, turbo will replace the correct one

```auto
class Comment < ApplicationRecord

  after_create_commit do
    # appending the comment
    broadcast_replace_to [post, :comments], target: "total_comments", partial: "posts/comment_count", locals: { post: post }
   end
end

```

---

<div class="post-metadata">

**Author:** ![GuillaumeGrassiant](https://yyz1.discourse-cdn.com/flex027/user_avatar/discuss.hotwired.dev/guillaumegrassiant/32/2461_2.png) [@GuillaumeGrassiant](https://discuss.hotwired.dev/u/GuillaumeGrassiant)\
**Post date:** [January 6, 2022, 2:09pm UTC](https://discuss.hotwired.dev/t/broadcasting-to-nested-turbo-frame-tag/3659/8 "2022-01-06T14:09:32Z")

</div>

Awesome!  
Thanks a lot 🙂 It works with the partial you mentioned.  
Have a good day.
