如何让带data-remote:true的Rails表单点击提交按钮时正常提交?
解决方案
要实现**按键自动保存(AJAX)+ 手动提交(常规表单提交)**的分离逻辑,核心是区分两种提交的触发源,避免手动提交时走AJAX流程。以下是具体修改步骤:
1. 修改Rails表单代码
给表单添加提交事件监听,同时给提交按钮绑定点击事件以清除自动保存超时:
<%= form_with(model: [player, report], id: "#{dom_id(report)}_form", class: "contents", data: { controller: "autosave", "autosave-target": "form", action: "ajax:success->autosave#success ajax:error->autosave#error submit->autosave#handleSubmit" }) do |form| %> <%= form.text_field :name, { class: "form-text-field", data: { action: "keyup->autosave#save" } } %> <%= form.submit class: "px-4 py-2 border border-transparent text-sm font-medium rounded-md shadow-sm text-white bg-purple-600 hover:bg-purple-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-purple-500", data: { action: "click->autosave#manualSubmit" } %> <% end %>
2. 修改Stimulus控制器
添加标记区分自动保存/手动提交,同时处理两种提交的逻辑分支:
import { Controller } from '@hotwired/stimulus' import Rails from '@rails/ujs' export default class extends Controller { static targets = ['form', 'status'] connect() { this.timeout = null this.duration = this.data.get('duration') || 1000 this.isAutosaving = false // 标记当前是否为自动保存触发的提交 console.log("Autosave enabled.") } save() { clearTimeout(this.timeout) this.timeout = setTimeout(() => { this.isAutosaving = true this.statusTarget.textContent = 'Saving...' Rails.fire(this.formTarget, 'submit') }, this.duration) } // 处理表单提交事件,区分自动/手动提交 handleSubmit(event) { if (!this.isAutosaving) { // 手动提交:阻止AJAX,执行常规表单提交 event.preventDefault() this.formTarget.removeAttribute('data-remote') this.formTarget.submit() } else { // 自动保存:保持AJAX提交,提交后重置标记 this.isAutosaving = false } } // 点击提交按钮时清除自动保存超时,避免冲突 manualSubmit() { clearTimeout(this.timeout) } success() { var date = new Date(); var hours = date.getHours(); var minutes = date.getMinutes(); var ampm = hours >= 12 ? 'pm' : 'am'; hours = hours % 12; hours = hours ? hours : 12; // 0点显示为12 var dateString = hours + ':' + minutes + ':' + date.getSeconds() + ' ' + ampm; this.setStatus("Last autosaved at " + date.getDate() + "/" + (date.getMonth()+1) + "/" + date.getFullYear() + " @ " + dateString.replace(/(^|\D)(\d)(?!\d)/g, '$10$2')) } error() { this.setStatus('Unable to Autosave!') } setStatus(message) { this.statusTarget.textContent = message } }
关键逻辑说明
- 标记区分:用
isAutosaving变量标记当前提交是否由自动保存触发 - 手动提交处理:点击提交按钮时先清除自动保存超时,提交事件中阻止AJAX,移除
data-remote属性后执行常规表单提交 - 自动保存处理:按键触发的自动保存仍走AJAX流程,提交后重置标记
内容的提问来源于stack exchange,提问作者daveomcd
相关产品推荐
相关产品推荐

