Rails Hotwire嵌套Turbo Frame用src懒加载时找不到框架的问题
Rails 8/Hotwire Turbo Frame 懒加载评论编辑功能异常问题解决
问题现象
使用Turbo Frame的src属性懒加载评论列表时,点击评论的编辑链接会触发Turbo错误:
Uncaught (in promise) Error: The response (200) did not contain the expected <turbo-frame id="comment_155e1b8a-7476-41fb-bbc1-812899c438d6">
但内联渲染评论列表时,编辑功能完全正常。
核心原因分析
- ID匹配错误:Turbo请求编辑页面后,会在响应中查找链接指定的
data-turbo-frame对应的ID,如果两者不匹配就会报错。懒加载场景下,可能存在评论partial中dom_id(comment, :edit)生成的ID与编辑页面Frame ID不一致的情况。 - 代码笔误:你的代码中存在明显的拼写错误(比如评论partial文件名
commmets/_comments.html.erb、用户详情页中错误的dom_id(skill, :edit)),这些笔误在懒加载场景下会被放大,导致Turbo无法正确识别目标Frame。 - 嵌套Frame上下文问题:懒加载的评论列表会被替换到父Frame内部,Turbo在处理嵌套Frame内的链接时,可能会错误解析目标Frame的上下文。
解决方案
1. 修正所有代码笔误
- 将评论partial文件名改为
comments/_comment.html.erb(单数,对应单个评论渲染,render @user.comments会自动遍历每个评论调用该partial)。 - 删除用户详情页中错误的
<%= turbo_frame_tag dom_id(skill, :edit) %>,Turbo会自动创建不存在的目标Frame,无需提前声明。
2. 确保ID完全匹配
评论partial(comments/_comment.html.erb)
确认编辑链接的data-turbo-frame生成的ID与编辑页面的Frame ID完全一致:
<%= turbo_frame_tag comment do %> <%= link_to edit_user_comment_path(comment.user, comment), data: { turbo_frame: dom_id(comment, :edit) } do %> edit comment <% end %> <%= comment.body %> <% end %>
编辑页面(comments/edit.html.erb)
确保Frame ID与链接指定的ID完全匹配:
<%= turbo_frame_tag dom_id(@comment, :edit) do %> <%= form_with(model: [@comment.user, @comment]) do |f| %> <%= f.text_area :body, value: @comment.body %> <%= f.submit "Update Comment" %> <% end %> <% end %>
3. 检查懒加载控制器逻辑
确保comments#index控制器正确传递变量,保证评论对象的完整性:
# app/controllers/comments_controller.rb def index @user = User.find(params[:user_id]) @comments = @user.comments.ordered end
4. 验证渲染后的HTML
在浏览器开发者工具中检查:
- 编辑链接的
data-turbo-frame属性值是否为comment_xxx_edit格式。 - 懒加载后的评论Frame是否正确嵌套在父Frame内,且每个评论的ID正确。
额外优化建议
如果需要在固定位置展示编辑表单,可以在用户详情页添加一个容器,让Turbo将编辑Frame插入到该容器中:
<%# users/show.html.erb %> <%= turbo_frame_tag dom_id(@user, "comments"), src: polymorphic_url([@user, :comments]) %> <!-- 编辑表单容器 --> <div id="comment_edit_container"></div>
然后修改编辑链接,指定插入目标:
<%= link_to edit_user_comment_path(comment.user, comment), data: { turbo_frame: dom_id(comment, :edit), turbo_target: "comment_edit_container" } do %> edit comment <% end %>
内容的提问来源于stack exchange,提问作者fluxsaas
相关产品推荐
相关产品推荐

