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

时间:2012-03-28 12:09:24

标签: ruby-on-rails-3 forms haml ujs

问题是我有一个远程表单,基于条件,id喜欢转换为非远程表单(使用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">

当我点击提交时,正如预期的那样,表单被提交为“AS 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 个答案:

答案 0 :(得分:38)

jQuery对于数据属性来说有点棘手,因为它们都是 读取HTML5数据标签以及绑定到的自己的存储 DOM元素,也称为数据。写入属性时 该值被复制到jQuerys自己的数据存储中(大概是 在调用data("remote")时。

然而,这只会发生 如果jQuery的数据为该名称为空。因此,设置属性只能使用一次,之后使用“缓存”值 即使属性发生变化。为了真正摆脱了 值,我们需要删除属性和jQuerys自己的存储 方法按顺序。原因是有一个高级别 (element.removeData(…))函数和低级函数(jQuery. removeData(element, …))。前者重新读取HTML5数据 属性并将其存储在jQuery自己的存储中。使用相当 不寻常的低级别功能显然也有效。

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

<强> TL; DR:

  • attr("data-remote") != data("remote")
  • 这两行使表格非远程(再次)。订单很重要。
  $("form").removeAttr("data-remote");
  $("form").removeData("remote");

如果您确实知道自己在寻找什么,那么就会记录下来:

StackOverflow不允许我发布两个以上的链接,但你可以猜测removeData一个。高级功能与低级功能相关联。

避免Rails 4 +中的令牌真实性错误: 正如Stan在下面评论的那样,只是执行上述操作会因InvalidAuthenticityToken错误而失败。解决方法很简单,详情请见此处:https://stackoverflow.com/a/19858504/1684530

答案 1 :(得分: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属性(如果存在)。