我们目前正在将我们的应用程序从 Vue.js 转移到 hotwire。我们在使用turbo_frames和ViewComponents时遇到了一个非常奇怪的错误。
我们有一个turbo_frame_tag用于聊天中的消息列表,然后有一个单独的表单,它点击控制器来创建新消息,然后重新渲染MessagesComponent。
我们遇到的错误是,不是替换原始turbo_frame的内容,而是渲染新的turbo_frame(除此之外,它渲染在文档的根部,甚至不在正确的组件内。)
我检查了turbo_frame id,它们都是正确的。?
版本 导轨:7.1.3 涡轮导轨:2.0.1
messages_component.html.erb
<%= tag.turbo_frame(id: "some_id") do %>
<div class="space-y-3">
<% messages.each do |message| %>
<%= render Atoms::MessageComponent.new(message:) %>
<% end %>
</div>
<% end %>
new_message_component.html.erb
<%= form_with(model: new_message, data: {turbo_frame: "some_id"}) do |f|%>.
<%= f.label :message%>
<%= f.hidden_field :owner_id, value: owner.id %>
<%= f.text_field :content %>
<%= f.submit "Send Message" %>
<% end %>
messages.controller.rb#create
def create
message = current_user.messages.create(message_params)
render Atoms::MessagesComponent.new(messages: messages.owner.messages)
end
我检查了请求类型,它是
text/vnd.turbo-stream.html
。
我还验证了我们的页面上只有 id 为 some_id
的元素。
任何帮助将不胜感激。
更新: 添加到此,我现在注意到新渲染的组件不在 html body 标记内,这非常奇怪。
响应必须是 HTML。
text/vnd.turbo-stream.html
格式适用于 Turbo 流。当您提交表单时,您可以使用 Turbo Stream 或 html 进行响应,请注意 ACCEPT 标头:
request.accept
#=> "text/vnd.turbo-stream.html, text/html, application/xhtml+xml"
# ^ ^
# `- TURBO_STREAM `- HTML
通常,当您渲染模板或部分模板时,rails 足够智能,可以为您的响应设置正确的内容类型,这是从扩展名
turbo_stream.erb
或 html.erb
推断出来的。当您渲染一个组件时,该逻辑不会被执行,您最终会以 TURBO_STREAM 格式进行响应,但您不会发送 <turbo-stream>
回来。
您必须使用
respond_to
块或显式设置 content_type
:
def create
message = current_user.messages.create(message_params)
respond_to do |format|
format.html { render Atoms::MessagesComponent.new(messages: messages.owner.messages) }
end
# or
render Atoms::MessagesComponent.new(messages: messages.owner.messages), content_type: "text/html"
end
新渲染的组件不在 html body 标签内
这是涡轮流行为,流被附加在文档的末尾,然后它们被任何 Turbo Stream 观察者和获取进程拾取,因为您的响应中没有
<turbo-stream>
标签,所以什么也没有发生: