我有一个表单,我希望每当任何输入字段更改时自动提交。我正在使用Turbo Streams,如果我使用onchange:"this.form.submit()"
,它不会被Turbo Streams捕获,Rails会使用标准的HTML响应。点击提交按钮时可以正常工作。我该如何解决这个问题?
我有一个表单,我希望每当任何输入字段更改时自动提交。我正在使用Turbo Streams,如果我使用onchange:"this.form.submit()"
,它不会被Turbo Streams捕获,Rails会使用标准的HTML响应。点击提交按钮时可以正常工作。我该如何解决这个问题?
在 hotwire 论坛上有一篇讨论,Mark Godwin 发现了为什么form.submit()
与 Turbo 不兼容:
Turbo 拦截表单提交事件,但奇怪的是,JS 的 formElement.submit() 方法不会触发提交事件。
而Jacob Daddario发现你可以使用 form.requestSubmit()
代替:
原来 Turbo-Stream 机制监听表单提交事件,但由于某些原因,submit() 函数不会触发表单提交事件。这意味着它将返回普通的 HTML 响应。不过,看起来还有另一种方法 requestSubmit() 可以发出表单提交事件。
所以你可以稍微更改你的代码,并使用 requestSubmit()
,如果浏览器支持,否则使用submit()
:
onchange: "this.form.requestSubmit ? this.form.requestSubmit() : this.form.submit()"
更新:
正如BenKoshy所指出的,Turbo 7.1.0 中添加了一个polyfill,以便您可以使用form.requestSubmit()
而不需要检查浏览器支持性,因此您可以将其添加到输入字段中:
onchange: "this.form.requestSubmit()"
我需要为一个包含大量表单的应用程序实现这个功能。最终我采用了 Stimulus 实现。以下是整个控制器的代码:
import { Controller } from "stimulus"
const _ = require("lodash")
export default class extends Controller {
connect() {
let that = this;
that.element.addEventListener('change', _.debounce(that.handleChange, 500))
}
handleChange(event) {
event.preventDefault()
// event.target.name // => "user[answer]"
// event.target.value // => <user input string>
event.target.form.requestSubmit()
}
}
这里它被用在一个只有一个文本输入框的表单中。注意控制器附加到了表单上而不是输入框上。
<%= turbo_frame_tag dom_id(form_model) do %>
<%= form_with model: form_model,
format: :turbo_stream,
html: { data: { controller: "buttonless-form" } } do |f| %>
<%= f.hidden_field :question_id, value: question.id %>
<%= f.text_field :answer_value, class: "input shadow wide", placeholder: "Enter your answer here" %>
<% end %>
<div id=<%= "question_#{question.id}_output" %>>
<p> <!-- feedback to the user shows up here via Turbo -->
</div>
<% end %> <!-- end turbo frame -->
form_with( ... method: :post )
,那么这个方法可以正常工作。但是如果你使用的是form_with( ... method: :get )
,那么表单将以HTML格式提交。为了修复这个问题,你可以使用form_with(... data: { turbo_stream: true })
。这适用于最新版本的turbo-rails 1.4.0。 - Volodymyr