如何修复Rails Turbo Frame切换局部视图时的「Content missing」错误?
修复Turbo切换局部视图时的「Content missing」错误
问题根源
- Turbo Frame ID冲突:外层
turbo_frame_tag与内部容器div使用了相同的questions-containerID,导致Turbo无法正确定位替换目标 - 链接路径错误:按钮链接指向了
questions_path(列表页)而非new_question_path(新建页),无法触发new动作的Turbo Stream响应 - 局部视图变量不一致:控制器传递了局部变量
question,但视图中使用的是实例变量@question - 表单结构缺失:局部视图没有包裹表单标签,无法处理POST请求
修复步骤
1. 修正new.html.erb的Turbo Frame结构与链接路径
将外层Turbo Frame的ID改为唯一值,同时修正链接指向new_question_path:
<div class="w-full"> <%= turbo_frame_tag "questions-tabs-container" do %> <div class="container mx-auto mb-10"> <div class="mx-5 lg:mx-40"> <div class="w-full flex"> <div class="flex border border-black flex-col"> <div class="flex w-full flex-col"> <div class="tab flex w-full"> <div class="flex w-1/2 justify-center items-center tablinks first"> <%= image_tag('globe.png', alt: 'Public Question', class: 'w-6 h-6 gray-icon') %> <%= image_tag('globe.png', alt: 'Public Question', class: 'w-6 h-6 colored-icon') %> <%= link_to "Public Question", new_question_path(status: "public_question"), class: "px-2", data: { turbo_frame: 'questions-container' } %> </div> <div class="flex w-1/2 justify-center items-center tablinks second"> <%= image_tag('lock.png', alt: 'Private Question', class: 'w-6 h-6 gray-icon') %> <%= image_tag('lock.png', alt: 'Private Question', class: 'w-6 h-6 colored-icon') %> <%= link_to "Private Question", new_question_path(status: "private_question"), class: "px-2", data: { turbo_frame: 'questions-container' } %> </div> </div> </div> <div id="questions-container"> <%= render "public_question", question: @question %> </div> </div> </div> </div> </div> <% end %> </div>
2. 修正控制器questions_controller.rb的Turbo Stream响应
确保替换目标是内部的questions-container div,并且局部变量传递正确:
def new @question = Question.new respond_to do |format| format.html format.turbo_stream do target = "questions-container" if params[:status] == "public_question" render turbo_stream: turbo_stream.replace( target, partial: 'questions/public_question', locals: { question: @question } ) elsif params[:status] == "private_question" render turbo_stream: turbo_stream.replace( target, partial: 'questions/private_question', locals: { question: @question } ) end end end end
3. 完善_public_question.html.erb的表单结构与变量引用
添加form_with包裹内容,将@question替换为局部变量question:
<%= form_with(model: question, class: "tabcontent w-full flex") do |form| %> <div class="flex w-full flex-col"> <div class="flex w-full flex-col"> <div class="flex flex-col"> <div class="flex space-x-3 w-full items-center"> <div class="flex h-10 w-10"> <%= image_tag('profile.png', alt: 'Profile Image' , class: 'w-full' ) %> </div> <div class="flex flex-col space-y-1"> <div class="flex space-x-2 items-center"> <%= render "users/current_user" %> </div> <div class="font-roboto text-sm font-normal offset-color"> <%= current_user.designation.name %>, <%= current_user.department.name %>, <%= current_user.zone.name %> </div> </div> </div> <div class="flex pt-3"> <%= form.hidden_field :is_private, value: false %> <%= form.text_area :content, class: "w-full font-roboto font-normal text-lg h-20", placeholder: "What is your Question?", required: true %> </div> <div class="flex py-4 space-x-2 w-full"> <% if question.attached_image.attached? %> <%= image_tag question.attached_image, alt: "Uploaded Image" , class: "w-full" %> <% end %> </div> </div> <div class="flex border border-black p-4 border-b w-full"> <div class="flex space-x-10 w-1/2"> <div class="font-roboto font-normal text-xl border border-blue px-5 py-2 rounded-full m-1 text-blue flex space-x-2 justify-center items-center"> <button> Add topics </button> </div> </div> <div class="flex space-x-1 justify-end w-1/2 items-center"> <button class="flex items-center font-roboto font-normal text-xl border border-gray px-5 py-2 rounded-full m-1 text-gray"> <%= image_tag("upload-2.png", class: "w-6 h-6" , alt: "Bronze Contributor" ) %> <span class="ml-2">Upload Image</span> </button> </div> </div> <div class="flex w-full border border-black p-4 border-b"> <div class="flex w-full space-x-3 items-center"> <button class="flex font-roboto text-base"> Tag Someone </button> <div class="flex space-x-2"> <div class="flex items-center font-roboto font-bold text-base"> <%= image_tag("person-add.png", alt: "Add Person" , class: "w-6 h-6" ) %> <span class="ml-2">Add a person</span> <input class="hidden" type="file" /> </div> </div> <p class="mr-2 py-2 text-gray italic font-roboto text-sm text-right"> *Optional </p> </div> </div> </div> <div class="flex bg-custom-gray-2 justify-center items-center border p-4 mt-4 w-full"> <%= form.submit "Post Question", class: "w-full px-4 rounded inline-flex items-center justify-center" %> </div> </div> <% end %>
4. 完善_private_question.html.erb的表单结构与变量引用
同样添加form_with并替换变量:
<%= form_with(model: question, class: "tabcontent w-full flex") do |form| %> <div class="flex w-full flex-col"> <div class="flex flex-col"> <div class="flex space-x-3 w-full items-center"> <div class="flex h-10 w-10"> <%= image_tag('profile.png', alt: 'Profile Image' , class: 'w-full' ) %> </div> <div class="flex flex-col space-y-1"> <div class="flex space-x-2 items-center"> <%= render "users/current_user" %> </div> <div class="font-roboto text-sm font-normal offset-color"> <%= current_user.designation.name %>, <%= current_user.department.name %>, <%= current_user.zone.name %> </div> </div> </div> <div class="flex pt-3"> <%= form.hidden_field :is_private, value: true %> <%= form.text_area :content, class: "w-full font-roboto font-normal text-lg h-20", placeholder: "What is your Question?", required: true %> </div> <div class="flex py-4 space-x-2 w-full"> <% if question.attached_image.attached? %> <%= image_tag question.attached_image, alt: "Uploaded Image" , class: "w-full" %> <% end %> </div> </div> <div class="flex border border-black p-4 border-b w-full"> <div class="flex space-x-10 w-1/2"> <div class="font-roboto font-normal text-xl border border-blue px-5 py-2 rounded-full m-1 text-blue flex space-x-2 justify-center items-center"> <button> Add topics </button> </div> </div> <div class="flex space-x-1 justify-end w-1/2 items-center"> <button class="flex items-center font-roboto font-normal text-xl border border-gray px-5 py-2 rounded-full m-1 text-gray"> <%= image_tag("upload-2.png", class: "w-6 h-6" , alt: "Bronze Contributor" ) %> <span class="ml-2">Upload Image</span> </button> </div> </div> <div class="flex w-full border border-black p-4 border-b"> <div class="flex w-full space-x-3 items-center"> <div class="flex space-x-2"> <div class="flex items-center font-roboto text-base"> <p>Ask this question privately to:</p> </div> <div class="flex items-center space-x-2"> <div class="flex items-center justify-center text-xl font-roboto bg-custom-gray border border-none rounded-full cursor-pointer"> <%= image_tag("person-add.png", alt: "Add Person" , class: "w-6 h-6" ) %> <span class="ml-2">Add a person</span> <input class="hidden" type="file" /> </div> </div> </div> </div> </div> <div class="flex bg-custom-gray-2 justify-center items-center border p-4 mt-4 w-full"> <%= form.submit "Post Question", class: "w-full px-4 rounded inline-flex items-center justify-center" %> </div> </div> <% end %>
关键说明
- 避免Turbo Frame与普通DOM元素ID重复,确保Turbo能精准定位替换目标
- 链接必须指向
new_question_path才能触发new动作的Turbo Stream响应 - 局部视图使用传递的局部变量而非实例变量,保证数据一致性
- 用
form_with包裹表单内容,确保POST请求能正确提交到服务器
内容的提问来源于stack exchange,提问作者Ornob Rahman
相关产品推荐
相关产品推荐

