使用JS更改< form>在Rails 3,HAML中从远程到非远程 [英] Use JS to change <form> from remote to non-remote in Rails 3, HAML

查看:173
本文介绍了使用JS更改< form>在Rails 3,HAML中从远程到非远程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

问题是我有一个远程表单,根据条件,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,因此我必须作为多部分提交,以便可以上传图像,并且我不能提交"AS JS" 现在,当我单击提交时,确实调用了控制器动作"regularAction",但其仍为"AS JS"

问题是,我还需要在HTML中进行哪些更改,以便可以以非xhr的形式提交表单?与标题有关吗?

解决方案

jQuery的数据属性有些棘手,因为两者 读取HTML5数据标签及其绑定到 DOM元素,也称为数据.写入属性时 该值将复制到jQuery自己的数据存储中(大概是 调用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

The problem is that i have a remote form that, based on condition, id like to convert to a non-remote form (using UJS), and then submit. note the form has a file upload.

Here's the details: I have initially rendered the remote form using

= form_for @myobj, :url => {:action=>"remoteAction", :controller=>"myobjects"}, :remote => true do |f|
... (f.fields....)

which produces the HTML:

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

when i click submit, as expected, the form is submitted 'AS JS'. in the controller action, i am doing some validation of the fields inside the submitted form. If all the validations pass, i execute the following .js.haml template:

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

which successfully changes the HTML on the page (witnessed via Firebug) to:

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

since the form contains an f.file_field, i have to submit as multipart so the image can be uploaded, and i cannot submit 'AS JS' now, when i click submit, the controller action 'regularAction' is indeed called, but its still 'AS JS'

the question is, what else do i need to change in the HTML so the form can be submitted non-xhr? is it related to the headers?

解决方案

jQuery is a bit tricky with the data attributes since it both reads the HTML5 data tags as well as its own storage bound to the DOM element, that is also called data. When writing to an attribute that value gets copied into jQuerys own data storage (presumably when data("remote") is being called).

However, this only happens if jQuery’s data is empty for that name. Thus setting the attribute will only work once, after that the "cached" value is being used even if the attribute changes. In order to really get rid of the value, we need to remove the attribute and jQuerys own storage method in that order. The reason is that there’s a high-level (element.removeData(…)) function and a low level one (jQuery. removeData(element, …)). The former re-reads the HTML5 data attribute and stores it in jQuery’s own storage. Using the rather unusual low level function obviously works as well.

Also, we do really need to remove the attribute -- setting it to false is not enough since Rails only checks if form.data('remote') is not undefined (look for it in jquery_ujs.js).

TL;DR:

  • attr("data-remote") != data("remote")
  • These two lines make a form non-remote (again). Order matters.

  $("form").removeAttr("data-remote");
  $("form").removeData("remote");

It’s documented, if you actually know what you’re looking for:

StackOverflow doesn’t allow me to post more than two links, but you can guess the removeData one. The high-level functions are linked from the low level ones.

Avoiding the token authenticity error in Rails 4+: As Stan commented below, just doing the above will fail with an InvalidAuthenticityToken error. The workaround is easy though, see here for details: https://stackoverflow.com/a/19858504/1684530

这篇关于使用JS更改&lt; form&gt;在Rails 3,HAML中从远程到非远程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆