迁移至Rails7的应用中Turbo Frame/Stream首次提交后失效求助
问题:Hotwire集成后仅首次提交有效,后续提交停滞
我正在将Hotwire集成到一个从Rails 6.1迁移至Rails 7的项目中,希望提交下拉框新值后用新版本表格替换原有表格,但目前仅首次提交正常,后续无法提交,陷入停滞状态。
相关代码
表格局部视图(documents/_edit_tag_table.html.erb)
<%= turbo_frame_tag "new_tag_#{tag_name}_#{issuer}" do %> <table class="table table-bordered" id="edit_table"> <thead> <tr> <th scope="col">Tag</th> <th scope="col">Acciones</th> </tr> </thead> <%= render partial: "document_tags/document_tag", locals: {document: document, tag_name: tag_name, issuer: issuer} %> </table> <% end %>
标签局部视图(document_tags/_document_tag.html.erb)
<tbody id="tags-table-body"> <% document.document_tags.each do |document_tag| %> <% if document_tag.tag&.tag_type&.name == tag_name %> <tr> <td><%= document_tag.tag.name %></td> <td> <%= button_to document_tag_path(document_tag, return_to: @redirect_url), method: :delete, data: { confirm: '¿Estás seguro que deseas eliminarlo?' }, class:"btn btn-outline-danger", remote: true do %> <i class="fas fa-trash-alt"></i> <% end %> </td> </tr> <% end %> <% end %> <tr> <% document_tag = DocumentTag.new %> <%= form_with(model: document_tag, local: true, data: { turbo_stream: true }) do |form|%> <% if document_tag.errors.any? %> <div id="error_explanation"> <h2><%= pluralize(document_tag.errors.count, "error") %> prohibited this document_tag from being saved:</h2> <ul> <% document_tag.errors.full_messages.each do |message| %> <li><%= message %></li> <% end %> </ul> </div> <% end %> <td> <% tag_type = TagType.find_by(name: tag_name) %> <% if tag_type %> <%= form.hidden_field :document_id, value: document.id %> <%= form.hidden_field :tag_type, value: tag_name %> <% if @redirect_url %> <%= form.hidden_field :return_to, value: @redirect_url %> <% end %> <%= form.collection_select(:tag_id, Tag.where(tag_type_id: tag_type.id), :id, :name, {:prompt=>true}, {class: 'form-control js-example-basic-single', id: tag_type.id, onchange: "this.form.requestSubmit()"}) %> <% end %> <td> <%= form.submit "Agregar tag", class: 'btn btn-primary' %> </td> <% end %> </tr> </tbody>
控制器代码(document_tags_controller.rb)
def create respond_to do |format| if @document_tag.save format.turbo_stream do render turbo_stream: turbo_stream.replace( "new_tag_#{@document_tag.tag.tag_type.name}_false", partial: "documents/edit_tag_table", locals: { document: @document_tag.document, tag_name: @document_tag.tag.tag_type.name, issuer: false } ) end format.html { redirect_to edit_document_path(@document_tag.document), notice: 'Se ha añadido el tag exitosamente.' } format.json { render :show, status: :created, location: @document_tag.document } else format.html { render :new } format.json { render json: @document_tag.errors, status: :unprocessable_entity } end end end
问题原因及修复方案
1. 事件绑定丢失(核心问题)
你用内联onchange: "this.form.requestSubmit()"绑定下拉框提交事件,但Turbo替换DOM后,新渲染的元素不会自动继承原有事件绑定,导致后续下拉框选择后无法触发提交。
修复:
使用Turbo内置的data-turbo-submit-on-change属性替代内联事件:
<%= form.collection_select( :tag_id, Tag.where(tag_type_id: tag_type.id), :id, :name, {prompt: true}, { class: 'form-control js-example-basic-single', id: "tag_id_#{document.id}_#{tag_type.id}", # 新增唯一ID避免冲突 data: { turbo_submit_on_change: true } } ) %>
2. Turbo Frame ID不匹配
控制器中硬编码了issuer: false,但初始渲染的Turbo Frame ID是new_tag_#{tag_name}_#{issuer},如果初始issuer不是false,替换后的Frame ID会和原ID不一致,导致后续Turbo操作失效。
修复:
- 在表单中添加
issuer隐藏字段,传递初始值:<%# 在document_tags/_document_tag.html.erb的form内添加 %> <%= form.hidden_field :issuer, value: issuer %> - 在控制器中使用提交的
issuer参数保持ID一致:# 控制器create方法中修改 render turbo_stream: turbo_stream.replace( "new_tag_#{@document_tag.tag.tag_type.name}_#{params[:document_tag][:issuer]}", partial: "documents/edit_tag_table", locals: { document: @document_tag.document, tag_name: @document_tag.tag.tag_type.name, issuer: params[:document_tag][:issuer] } ) - 确保
document_tag_params允许issuer参数。
3. 表单Turbo设置冲突
Rails 7中form_with默认使用Turbo驱动,你同时设置local: true和data: { turbo_stream: true }会导致Turbo无法正确处理后续请求。
修复:
移除local: true,保留data: { turbo_stream: true }:
<%= form_with(model: document_tag, data: { turbo_stream: true }) do |form|%>
内容的提问来源于stack exchange,提问作者charlie
相关产品推荐
相关产品推荐

