You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Turbo嵌套表单问题:添加/删除按钮失效及参数错误

Turbo动态嵌套表单问题修复方案

问题概述

  1. 保存父表单后返回编辑页面可显示嵌套项,但Delete按钮无响应;
  2. Add Option按钮未触发子项创建,反而调用父控制器surveys/questions_controller#create,报":title, :description, :question_options_attributes"参数不允许错误。

核心错误分析与修复

一、Add Option按钮错误修复

1. 路由定义错误

当前路由将create定义为member动作(需要对应资源实例),但create是创建新资源的collection动作,修正路由:

resources :surveys, param: :slug do
  resources :sections, controller: "surveys/sections", param: :sec_num
  resources :questions, controller: "surveys/questions", param: :position do
    resources :options, controller: "surveys/questions/options", 
              only: [:create, :destroy], param: :index
  end
end

此定义会自动生成:

  • POST请求:survey_question_options_path(对应create动作)
  • DELETE请求:survey_question_option_path(对应destroy动作)

2. Options控制器缺失create方法

添加create方法,构建新选项并返回Turbo流响应:

class Surveys::Questions::OptionsController < Surveys::QuestionsController
  before_action :setup

  def create
    # 注意:模型关联是has_many :question_options,不是options
    @option = @question.question_options.build
    @options = @question.question_options + [@option]
    respond_to do |format|
      format.turbo_stream
    end
  end

  def destroy
    @option = @question.question_options.find(params[:id])
    respond_to do |format|
      format.turbo_stream
    end
  end

  private

  def setup
    @survey = Survey.find_by(slug: params[:survey_slug])
    @section = @survey.sections.find_by(section_number: params[:sec_num])
    @question = @section.questions.find_by(position: params[:question_position])
  end
end

3. 视图中路径与关联调用错误

  • 修正Add按钮的路径为collection路由:
= f.submit "Add Option", formaction: survey_question_options_path(survey_slug: q.survey_section.survey.slug, question_position: q.position, sec_num: q.survey_section.section_number), formmethod: :post, formnovalidate: true, id: "add_option"
  • 统一模型关联调用:将所有@question.options/q.options改为@question.question_options/q.question_options(模型中定义的是has_many :question_options)

4. 修正create.turbo_stream.haml模板错误

将模板中的task_form改为of,并更新Add按钮的index参数:

= fields model: @question do |f|
  = f.fields_for :question_options, @options, child_index: params[:index] do |of|
    = turbo_stream.replace "add_option" do
      = f.submit "Add Option", formaction: survey_question_options_path(survey_slug: @survey.slug, question_position: @question.position, sec_num: @section.section_number, index: @options.size), formmethod: :post, formnovalidate: true, id: "add_option"

    = turbo_stream.append "options" do
      = render "surveys/questions/options/form", form: of, q: @question

二、Delete按钮无响应修复

1. 修正destroy.turbo_stream.haml模板逻辑

添加标记删除的隐藏字段到父表单,再移除对应选项的Turbo帧:

= turbo_stream.append "options" do
  = fields_for :survey_question, @question do |f|
    = f.fields_for :question_options, @option, child_index: params[:index] do |of|
      = of.hidden_field :id
      = of.hidden_field :_destroy, value: true

= turbo_stream.remove "question_#{@question.id}_option_#{params[:index]}"

2. 移除Delete按钮的Turbo帧限制

删除按钮的data-turbo-frame属性,让Turbo全局处理响应:

= form.submit "Delete", formaction: survey_question_option_path(survey_slug: q.survey_section.survey.slug, question_position: q.position, index: form.index, id: form.object.id, sec_num: q.survey_section.section_number), formmethod: :delete, formnovalidate: true

三、其他细节修正

  1. 父控制器update_params拼写错误:将:survey_setion_id改为:survey_section_id
def update_params
  params.require(:survey_question).permit(:survey_section_id, :position, :question_type, 
      :title, :description, question_options_attributes: [:id, :_destroy, :name, 
          :logic, :sub_logic])
end
  1. 父控制器edit方法中关联调用修正:
def edit
    @option = @question.question_options.build
    render partial: "surveys/questions/edit", locals: {q: @question, 
        survey: @survey, section: @section, option: @option}
end

内容的提问来源于stack exchange,提问作者Patrick Vellia

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 02:24:55