使用JS在Rails 3中将<form>从远程更改为非远程,HAML

17
问题是,我有一个远程表单,根据条件,我想使用UJS将其转换为非远程表单,然后提交。注意,该表单具有文件上传功能。
以下是详细信息:我最初使用的是远程表单进行呈现。
= form_for @myobj, :url => {:action=>"remoteAction", :controller=>"myobjects"}, :remote => true do |f|
... (f.fields....)

这将生成以下HTML:

<form id="new_myobj" class="new_myobj" method="post" accept-charset="UTF-8" data-remote="true" action="/remoteAction">

当我点击提交按钮时,正如预期的那样,表单会以JS方式提交。 在控制器动作中,我对提交表单中的字段进行一些验证。 如果所有验证都通过,我将执行以下.js.haml模板:

$('form#new_myobj').removeAttr("data-remote");
$('form#new_myobj').attr('enctype', 'multipart/form-data');
$('form#new_myobj').attr('action', '/myobjects/regularAction');

成功地更改了页面上的 HTML(通过 Firebug 观察到)为:

<form id="new_myobj" class="new_myobj" method="post" accept-charset="UTF-8" enctype="multipart/form-data" action="/myobjects/regularAction">

由于表单包含一个f.file_field,所以必须以multipart方式提交,以便可以上传图像,并且我不能使用“AS JS”进行提交。 现在,当我点击提交时,控制器操作“regularAction”确实被调用,但它仍然是“AS JS”。

问题是,我还需要更改HTML中的什么以便可以非XHR提交表单?这是否与头信息有关?

2个回答

42

由于jQuery同时读取HTML5数据标记和绑定到DOM元素上的自己的存储数据,因此处理数据属性有些棘手,该存储数据也称为data。当写入属性时,该值会被复制到jQuery自己的数据存储中(大概是在调用data("remote")时)。

但是,只有当某个名称的jQuery数据为空时,才会发生这种情况。因此,"cached"值将使用一次后,即使属性更改也将继续使用。为了真正摆脱该值,我们需要按照顺序删除属性和jQuery自己的存储方法(element.removeData(...))。原因是有一个高级别的函数(element.removeData(…))和一个低级别的函数(jQuery.removeData(element, …))。前者重新读取HTML5数据属性并将其存储在jQuery自己的存储中。使用相对不常见的低级别函数显然也可以。

此外,我们确实需要删除属性--将其设置为false是不够的,因为Rails仅检查form.data('remote')是否未定义(在jquery_ujs.js中查找)。

简而言之:

  • attr("data-remote") != data("remote")
  • 这两行代码使表单变成非远程,而且顺序很重要。
  $("form").removeAttr("data-remote");
  $("form").removeData("remote");

如果您真正了解要查找什么,这是有文档支持的:

StackOverflow不允许我发布超过两个链接,但您可以猜测removeData的链接。高级函数从低级函数中链接。

在Rails 4+中避免令牌真实性错误:如下面的Stan评论所述,仅执行以上操作将导致InvalidAuthenticityToken错误。 然而,解决方法很简单,请参见此处以获取详细信息:https://dev59.com/WmIk5IYBdhLWcg3wPcCB#19858504


3
顺便提一下,这种方法在Rails 4中会返回“无法验证CSRF令牌真实性”错误。 - Stan
怎么样把表单再次设为远程? - coderVishal

4
问题在于你禁用 Ajax 提交的方法不太正确。你需要取消已经由 rails.js(Rails UJS 适配器)添加到表单中的 JavaScript 事件。 你可以通过以下方式实现: $('form#new_myobj').unbind() 解除绑定到表单上的所有事件。还需要 $('form#new_myobj').removeAttr('data-remote')$('form#new_myobj').removeAttr('data-type') 来删除 data-remotedata-type 属性(如果存在)。

感谢您的建议,因此我在我的js.haml模板中添加了unbind()调用,但第二个提交仍然会转到“regularAction”操作“AS JS”。 - Sami Begg
我需要解绑其他组件吗? - Sami Begg

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接