You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让带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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 14:30:39