处理数据禁用的热线方式是什么?

pup*_*eno 5 javascript ruby-on-rails stimulusjs hotwire-rails turbo

我开始在我的 Rails 应用程序中使用Hotwire,我实现了类似于教程视频的内容,其中提交了一个表单并刷新了页面的另一部分。就像在视频中一样,我必须实现自己的重置表单控制器:

import {Controller} from "stimulus"

export default class extends Controller {
  reset() {
    this.element.reset()
  }
}
Run Code Online (Sandbox Code Playgroud)

重置表单中的值。表格看起来像:

<%= form_with(model: @invitation,
              data: {controller: "reset-form",
                     action: "turbo:submit-end->reset-form#reset"}) do |form| %>
  <!-- other form elements -->
  <%= form.submit "Invite" %>
<% end %>
Run Code Online (Sandbox Code Playgroud)

它在按钮中生成如下:

<input type="submit" name="commit" value="Invite" data-disable-with="Invite">
Run Code Online (Sandbox Code Playgroud)

因为有一个data-disable-with, 当你按下按钮时,它会被禁用以避免双击提交,这很好。问题是this.element.reset()没有重置它。

处理这个问题的正确方法是什么?

我不是在寻找解决方法,我知道很多,但我正在寻找解决此问题的干净方法。

这是由 UJS 引起的按钮禁用吗?这是否意味着不应在 Stimulus 应用程序中使用 UJS?

我可以从resetJavaScript 函数重新启用按钮,但如果输入按钮是这样指定的:

<%= form.submit "Invite", data: {disable_with: "Inviting, please wait..."} %>
Run Code Online (Sandbox Code Playgroud)

然后value按钮的原始标签 ( ) 丢失了,我没有办法重新建立它,这让我觉得无论是在实现这个功能(UJS?)它不是为 hotwire/spa 应用程序设计的,并且期望一个完全重新加载页面。

我可以扔:

config.action_view.automatically_disable_submit_tag = false
Run Code Online (Sandbox Code Playgroud)

并使用 Stimulus 控制器实现我自己的双击预防,但这感觉不对。问题不在于属性,data-disable-with而在于它是如何实现的。

Ale*_*lex 8

Turbo已经禁用提交按钮一段时间了,最​​近添加了 UJS 的data-turbo-submits-with替代方案: data-disable-with

# available since: turbo v7.3.0 (turbo-rails v1.4.0) thx @PaulOdeon
<%= form_with model: @invitation do |form| %>
  <%= form.submit "Invite", data: {turbo_submits_with: "Inviting..."} %>
<% end %>
Run Code Online (Sandbox Code Playgroud)

重置表单是可选的:

<%= form_with model: @invitation, data: {
  controller: "reset-form",
  action: "turbo:submit-end->reset-form#reset"
} do |form| %>
  <%= form.submit "Invite", data: {turbo_submits_with: "Inviting..."} %>
<% end %>
# NOTE: form reset is implemented as stimulus controller in the question
Run Code Online (Sandbox Code Playgroud)

https://turbo.hotwired.dev/reference/attributes


是的,你应该把这个放进去:

config.action_view.automatically_disable_submit_tag = false
Run Code Online (Sandbox Code Playgroud)

它只添加data-disable-with属性,这是UJS特定的,不会影响Turbo


不过,以前也不是不可以。如果您想实现自己的自定义行为,这是一个简化的示例。为了在这里明确区分,我使用非 Turbo 和非 ujs 属性(Turbodisabled仅为我们设置和删除属性):

config.action_view.automatically_disable_submit_tag = false
Run Code Online (Sandbox Code Playgroud)

对于简单的一键操作,您可以跳过刺激并仅使用Turbo事件:

<%= form_with model: @invitation, data: {reset: true} do |form| %>
  <%= form.submit "Invite", data: {disable_append: "..."} %>
<% end %>
Run Code Online (Sandbox Code Playgroud)

这几乎就是现在 Turbo 中实际完成的方式:
https://github.com/hotwired/turbo/blob/v7.3.0/src/core/drive/form_submission.ts#L217-L239


Aid*_*les 0

根据用户操作替换页面上的 HTML 内容的最“热线方式”是使用 Turbo 流响应。

如果我理解正确的话,您希望在表单提交后将表单(或只是按钮)返回到其原始状态。

你可以用涡轮框架包裹你的表格,就像这样

<%= turbo_frame_tag dom_id(@invitation) do %>
  <%= form_with(...) %>
  <% end %>
<% end %>
Run Code Online (Sandbox Code Playgroud)

然后,就像 @stwienert 所说,让您的控制器返回一个format.turbo_stream响应,为您的表单呈现部分/模板。以下是改编自Turbo 文档的Turbo_stream 响应的示例:

format.turbo_stream do
  render turbo_stream: turbo_stream.replace(@invitation, partial: "your/form",
    locals: { invitation: @invitation }) # or Invitation.new, perhaps
end
Run Code Online (Sandbox Code Playgroud)

目标是让控制器响应以表单的 DOM id 为目标,这样在表单提交时,您的数据就会得到适当的处理,然后客户端会收到一个 Turbo 流响应,其中包含您想要在 Turbo_frame 标记内看到的 HTML。

如果你只想替换按钮,只将按钮包装在turbo_frame中,给它一个唯一的DOM id,然后将该ID传递给turbo_stream.replace/append/etc,例如turbo_stream.replace(:button_dom_id_here, partial: ...)