【问题标题】:Rails form submission not happening in the backgroundRails 表单提交不在后台发生
【发布时间】:2019-01-21 06:11:01
【问题描述】:

我有一个 Rails 5.2 应用程序,我在其中使用 form_with,它正在生成此 HTML:

<form id="post-0" class="" action="/posts.js" accept-charset="UTF-8" data-remote="true" method="post">

表单已成功提交到 PostController 的 create 操作。

  def create
    @post = current_user.account.posts.new(post_params)
    respond_to do |format|
      if @post.save
        format.html { redirect_to posts_path, notice: 'Post added.' }
        format.js { render :create, status: :created }
      else
        format.html { render :index }
        format.js { render :create, status: :unprocessable_entity }
      end
    end
  end

然后渲染 JS 视图:
app/views/posts/create.js.erb

alert('created');

但是,在我的浏览器中,我确实被重定向到 http://localhost:3000/posts.js,它显示了 javascript 代码。意思是,表单提交没有似乎在后台发生。

我本来希望仍然停留在表单所在的页面上,并显示一个 Javascript 警报,显示“已创建”。

我错过了什么愚蠢的事情吗?在我看来,form_with 一定是我做的不对。

我尝试将其换成form_for @post, remote: true, format: :js do ...,但遇到了同样的问题。

此时,我无法确定问题出在显示表单的 View 中,还是出在 Controller 的 create 操作中。控制器正在呈现create.js.erb,显示的URL是http://localhost:3000/posts.js,这似乎表明这是视图中的表单问题。

这个应用程序是 Rails 5.2。我不确定它是否相关,但我已经删除了 Webpacker 的资产管道,我 确实 安装了 rails-ujs (因为它在这些 link_to 链接中按预期显示确认对话框@ 987654334@

【问题讨论】:

  • 从 format.js 中删除这个 { render :create, status: :created } 并重试。 @Turgs
  • 同样的问题。没有变化@wasipeer
  • 现在检查浏览器控制台是否有可能的错误
  • 您是否尝试指定action 名称?像这样:format.js { render action: 'create', status: :created } 通常你甚至不需要指定 aciton,它会默认搜索 create.js.erb

标签: ruby-on-rails ajax


【解决方案1】:

由于多种原因,表单提交可能发生在本地(即非远程)。

使用 form_with 时可能发生本地提交的一些常见原因包括:

本地:真

local 属性对于form_with 是可选的。如果未提供,form_with 将按默认设置local: false

  • true 将表单设置为本地提交(标准表单提交),而不是远程/异步。

  • false 会将表单设置为远程/异步提交。

false 以外的任何值(包括:false,它是一个符号 而不是布尔值)将被解释为true 的值(即。本地提交)。

Javascript 触发表单提交

尽管 local 属性的设置应触发远程/异步表单提交,但如果您通过 Javascript 触发表单 submit 事件,表单可能仍会在本地提交。

在有问题的示例中,form_with 使用生成的 HTML 符合预期,因此提供给 form_with 的属性在这种情况下不是问题。

如果使用 javascript 提交表单,这可能是问题所在。例如,即使表单上有data-remote="true",这个javascript也会有问题:

document.getElementById('form-0').submit();

这会提交表单,但 doesn't raise a submit eventrails-ujs 通过 onsubmit 事件处理程序进行拦截。

使用Rails Unobtrusive Javascript Adapter

要让 javascript 触发表单提交(无论您使用的是 jQuery、Stimulus JS 还是其他任何东西),您需要使用rails-ujs(或jquery-ujs)将为您拦截的机制。

Rails 在rails-ujs 中提供了Rails.fire 自定义javascript 事件包装器,可以这样使用:

Rails.fire(document.getElementById('form-0'), 'submit');

【讨论】:

  • 通过javascript的原生submit()调用触发表单提交是我的问题。我现在使用Rails.fire,效果很好。
  • RE 刚刚删除的 Ruby 问题,从 shell 中可以确定当前的 ruby​​ 版本:ruby -v #=&gt; ruby 2.6.3p62 (2019-04-16 revision 67580) [x86_64-linux]。如果您使用 RVM(参见 rvm.io)管理 Ruby 版本和 gem,您可以(从 shell)执行 rvm list known 以获取已知 Ruby 版本的列表,并可以使用命令 rvm install 2.6.3 安装一个(例如 v2.6.3) .您应该能够使用此信息来创建以您指定的时间间隔运行的cron job。当我认为你已经看到它时,我会删除它。
  • 我可以在提供local: true的同时使用Rails.fire(document.getElementById('form-0'), 'submit')吗?
  • 请注意,可能只是切线相关,我的 Rails 应用程序有问题,它绝对拒绝更新并保存到我正确配置的 psql 数据库。此修复使一切按预期工作;更改仅保存在本地,现在数据库按应有的方式更新。太棒了。
【解决方案2】:

你犯了一个非常基本的错误。通过使用ajax,您不能使用format.js。这个Ruby 模块用于重定向页面。相反,您应该使用render json: { status: 200}

【讨论】:

  • 谢谢。我一直使用format.js 作为回复。它可以工作,但在这种情况下,表单本身是如何提交的。
【解决方案3】:

在 Upwork 上看到了你的工作。无需为此花费 100 美元!

<%= form_with url: content_export_path, method: :post, id: 'ce_form1', data: { remote: true } %>

看看remote: true 声明在哪里...(在数据散列中)

让我知道这是否有效。

【讨论】:

  • 谢谢。在为表单元素生成的 HTML 中,它已经在生成 data-remote="true"
猜你喜欢
  • 2010-11-17
  • 1970-01-01
  • 2019-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-11
相关资源
最近更新 更多