В настоящее время мы находимся в процессе перевода нашего приложения с Vue.js на Hotwire. Мы только что столкнулись с очень странной ошибкой при использовании Turbo_frames и ViewComponents.
У нас есть Turbo_frame_tag для списка сообщений в чате, а затем отдельная форма, которая обращается к контроллеру для создания нового сообщения, а затем повторно отображает MessagesComponent.
Ошибка, с которой мы столкнулись, заключается в том, что вместо замены содержимого исходного турбо_фрейма отображается новый турбо_фрейм (вдобавок к этому он отображается в корне документа, даже не в правильном компоненте).
Я проверил идентификаторы Turbo_frame, и все они верны.?
Версии рельсы: 7.1.3 турбо-рельсы: 2.0.1
messages_comComponent.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_comComponent.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.
Я также проверил, что на нашей странице есть только элемент с идентификатором some_id.
Любая помощь будет оценена.
Обновлять: Вдобавок к этому я заметил, что недавно визуализированный компонент не находится внутри тега html body, что очень странно.





Ответ должен быть HTML. text/vnd.turbo-stream.html формат предназначен для турбо-стримов. Отправляя форму, вы можете ответить турбопотоком или 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>, ничего не происходит: