Rails:无法提交通过Ajax加载的远程表单

目标

我有一个包含Rails后端的项目列表的页面。 我希望能够通过Rails UJS使用Ajax调用来编辑该列表中的行。

途径

我在每行的末尾添加了一个编辑按钮。 编辑按钮是link_to ... :remote => true 。 单击它会再次加载列表,但所选行将处于编辑模式。 可编辑行嵌入在form ... :remote => true 。 该行中的保存按钮是一个submit按钮。

index.html.haml

 #editor %table - @items.each do |item| %tr = render :partial => 'row', :locals => { :item => item } 

_row.html.haml

 ... %td // a number of columns with attributes ... %td = link_to t("actions.edit"), edit_item_path(item), :remote => true = link_to t("actions.delete"), item_path(item), :remote => true, :method => :delete, :data => { :confirm => "Are you sure?" } 

edit.html.haml

 #editor %table - @items.each do |item| %tr - if item == @item = form_for @item, :url => item_path(@item), :remote => true, do |f| = render :partial => "row_form", :locals => { :f => f } - else = render :partial => 'row', :locals => { :item => item } 

_row_form.html.haml

 ... %td // a number of columns with editable attributes ... %td %button{ :type => "submit" }=t("actions.save") = link_to t("actions.cancel"), items_path, :remote => true 

Ajax响应处理

 $("#editor").on("ajax:success", function(event, data, status, xhr) { $("#editor").html($(data).find("#editor").html()); }); 

问题

当我在编辑模式/items/12/edit加载列表页面时, /items/12/edit的行是可编辑的。 单击保存按钮正确地通过Ajax提交表单并加载/items索引部分,用jQuery替换可编辑列表。 再次单击编辑按钮,使用嵌入的表单再次加载编辑页面(例如/items/12/edit )。 只有这次,单击保存按钮时才会再提交表单。 似乎提交事件处理程序未附加到动态加载的远程表单。

如何通过Ajax提交加载的远程表单,最好使用Rails UJS方法?

重复

我知道这个问题有重复,但没有一个得到回答。 我希望有人最终得出一个明确的答案。

  • 在文档就绪未提交后,通过Ajax加载Rails远程表单
  • :remote => true / data-remote在通过ajax加载的表单上

问题是DOM是由javascript修改的,并且回调(在你的例子中ajax成功)只在DOM init上初始化。 所以当DOM改变时(部分#editor)回调没有用。

因此,只要您使用javascript更改DOM,就应该重新初始化此回调

 $("#editor").on("ajax:success", function(event, data, status, xhr) { $("#editor").html($(data).find("#editor").html()); }); 

前段时间jQuery的function叫做“live”。 它的工作方式类似于“on”,但跟踪了DOM的变化。 但是在当前版本的jQuery中,这个函数已被弃用,因为它很慢。

希望你能理解我的英语不好=)

我使用它的方法是使用内置的Railsfunction:

  1. 在控制器的编辑操作中,将format.js添加到respond_to块。 这允许您创建一个edit.js.erb文件,您可以使用该文件将编辑表单加载到DOM中。
  2. 然后在同一控制器的更新操作中,再次将format.js添加到respond_to块,并拥有一个update.js.erb文件,该文件通过jQuery执行必要的DOM操作。

我确信在网上的教程中会对此进行进一步的解释,但我终于明白了它如何工作而无需调用jquery ajax方法在CodeSchool.com上 。

我发现了问题! 感谢@Jake Smith和@Parandroid的答案提示。 这是我在两个步骤中找到的内容。

寻找1

虽然获得ajax:success被解雇似乎不是问题,但它确实看起来像表单处理在$("#editor")选择器上100%正确工作。 至少需要$("#editor form") ,但如果我们从索引页面开始,它可能不起作用,索引页面还没有包含表单。 所以@Jake Smith建议的方法似乎是最强大的方法。 这导致:

edit.html.haml

 #editor = render :partial => "edit" 

edit.js.erb

 $('#editor').html('<%= escape_javascript render("edit") %>'); 

_edit.html.haml(仍然不能正常工作)

 %table - @items.each do |item| %tr - if item == @item = form_for @item, :url => item_path(@item), :remote => true, do |f| = render :partial => "row_form", :locals => { :f => f } - else = render :partial => 'row', :locals => { :item => item } 

但仍然没有导致工作提交按钮。 直到我发现出了什么问题……

发现2

上面的解决方案确实给了提交按钮普通的POST行为,服务器不喜欢它,因为它期望PUT到达update操作。 Rails通过生成具有值PUT的隐藏_method字段来实现此目的。 我发现rails在_edit.html.haml部分的顶部不是form标签内部生成了这个字段(以及其他几个关键的隐藏字段)! 所以我将表单移动到部分的顶部,它工作了!

_edit.html.haml(工作!)

 = form_for @item, :url => item_path(@item), :remote => true, do |f| %table - @items.each do |item| %tr - if item == @item = render :partial => "row_form", :locals => { :f => f } - else = render :partial => 'row', :locals => { :item => item } 

谁会猜到……

我有一个类似于这个的问题,通过ajax加载的表单没有提交,这是由于Turbolinks,我发现解决方案是将我的事件绑定到正文而不是元素,相关的答案在这个post:

如何使用$(document).on(“点击..在<标签上?

对我来说问题是点击标签,所以我不得不改变

$('label').click(function...

$('body').on('click', 'label', function

我有同样的问题,最后了解原因。 您的html源必须由以下forms组成。

  

似乎某些浏览器(包括Chrome和Firefox)无法正确处理此类嵌套标记。

在用其他类似ul / li替换table / tr / td标签后,我可以成功提交重新呈现的表单。