11

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

import {Controller} from "stimulus"

export default class extends Controller {
  reset() {
    this.element.reset()
  }
}

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

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

在按钮中生成如下:

<input type="submit" name="commit" value="Invite" data-disable-with="Invite">

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

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

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

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

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

<%= form.submit "Invite", data: {disable_with: "Inviting, please wait..."} %>

value然后按钮的原始标签 (完全重新加载页面。

我可以扔:

config.action_view.automatically_disable_submit_tag = false

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

4

2 回答 2

0

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

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

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

<%= turbo_frame_tag dom_id(@invitation) do %>
  <%= form_with(...) %>
  <% end %>
<% end %>

然后,就像@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

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

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

于 2021-05-25T16:46:12.320 回答
-1

我可能会将“原始”文本添加到 form.submit:

<% = form.submit "Invite", data: { 
  disable_with: "...", original: "Invite", "data-reset-form-button-target" } %>

然后你可以增强你的刺激控制器:

 static targets = ["button"]
 reset() {
   this.element.reset()
   this.buttonTarget.value  = this.buttonTarget.dataset.original
 }

无法测试它,只是乱涂乱画。

于 2021-04-17T20:33:33.097 回答