Hotwire Discussion

ViewComponents not rendering with Rails stream helper?

Greetings!

I had a quick question about rendering a ViewComponent (or something that responds to render_in) using the Turbo::Streams::TagBuilder helper. From what I can tell, this should be valid code:

respond_to do |format|
    format.turbo_stream do
      render turbo_stream: turbo_stream.prepend(:add_new_user, template: NotificationComponent.new(type: :warning, content: "Email in use"))
    end
end

From my understanding, this should return the NotificationComponent’s markup from render_in as the the content of <template>. Instead I’m seeing the class inspect output when this is prepended: <notificationcomponent:0x00007fe5eca77d60></notificationcomponent:0x00007fe5eca77d60>.

I’ve tried different keywords and for now have settled on creating a partial that renders this Component and using that. My question is am I missing something obvious here that allows you to render a component directly, or is there room to add a new component rendering keyword that can support this behavior in turbo-rails?

Thanks for any feedback or ideas!

This works for ViewComponents:

<%= turbo_stream.update "frame" do %> <%= render Component.new %> <% end %>

That was the solution that I ended up going with for now. I might dabble and see if I can get a more direct way to render it without having to use a template file.

1 Like

I use this way to render ViewComponent in controller without the partial.:

s = turbo_stream.replace dom_id do
  view_context.render(MessageComponent.new(message: @message))
end
render turbo_stream: s
1 Like

Interesting, I think the template file is a better and ‘correct’ solution

Probably so, I’m new to both ViewComponents and Turbo ( obviously :slight_smile: ). I was thinking that, since frames lend themselves to partial content by design, it might be cool to have a more streamlined API for rendering a component. I’m using the inline approach now and it’s working for my purposes.

1 Like