启用append_to_body后Rails表单无法通过Stimulus提交求助
问题原因
设置append_to_body: true后,选项列表的DOM元素被移动到了<body>标签下,脱离了原表单的DOM层级。你绑定在表单上的input->search#submit事件依赖事件冒泡触发,但单选按钮的input事件冒泡到<body>就会终止,无法到达表单元素,因此Stimulus控制器的submit方法不会被调用。
解决方案
以下是两种可行的修复方式:
方式一:给单选按钮直接绑定Stimulus动作
修改视图中的radio_button生成代码,给每个单选按钮添加data-action属性,直接触发search控制器的submit方法:
= polaris_option_list(title_hidden: true) do |list| - list.radio_button( label: t("All"), value: "", name: "q[account_type_eq]", checked: @q.account_type_eq.blank?, data: { action: "input->search#submit" } ) - list.radio_button( label: t("Equity"), value: "Equity", name: "q[account_type_eq]", checked: @q.account_type_eq == "Equity", data: { action: "input->search#submit" } ) # 其他单选按钮同理添加data-action属性
这样每个单选按钮的input事件都会直接调用search控制器的submit方法,不受DOM层级影响。
方式二:修改Stimulus控制器,使用事件委托监听全局输入事件
如果不想逐个修改单选按钮,可以调整Stimulus控制器,通过事件委托监听document内的目标单选按钮事件,然后找到对应表单提交:
import { Controller } from "@hotwired/stimulus"; import { useDebounce } from "stimulus-use"; export default class extends Controller { static debounces = ["submit"]; connect() { useDebounce(this, { wait: 300 }); // 监听document内的account_type_eq单选按钮的input事件 document.addEventListener("input", (e) => { if (e.target.name === "q[account_type_eq]") { this.submit(); } }); } submit() { this.element.requestSubmit(); } }
这种方式不需要修改视图代码,通过全局事件委托捕捉目标元素的事件,然后触发表单提交。
额外提示
如果你的项目中使用的Polaris组件库支持自定义append_to目标,可以尝试将popover append到表单所在的容器(比如card的section),而不是body,这样DOM层级保持在表单内,原有的事件绑定依然有效,同时避免下拉菜单重叠问题。比如修改popover_arguments:
def popover_arguments { sectioned: @sectioned, style: ("width: #{@width}" if @width.present?), position: :below, alignment: :left, append_to: "#form-container-id" # 替换为表单所在容器的ID } end
记得给表单所在的card section添加对应的ID:
- card.section(id: "form-container-id") do
内容的提问来源于stack exchange,提问作者Muhammad Zubair
相关产品推荐
相关产品推荐

