Javascript Rails/Ajax在提交后将表单从创建更改为更新

Javascript Rails/Ajax在提交后将表单从创建更改为更新,javascript,jquery,ruby-on-rails,ajax,forms,Javascript,Jquery,Ruby On Rails,Ajax,Forms,所以我想玩一个明星评级页面,在那里我有5个评级问题,你可以评级一次(创建)并在任何给定时间更新你的评级。评级表单是ajaxified的,但问题是表单元素在提交后仍然是一个Create方法,而不是update方法 我遵循了一个非常酷的教程,但是表单更新为正确的方法时缺少了一个部分 这是密码 我有一个部分rating\u questions/\u quick\u form.html.erb中的表单,每个评级表单都有一个嵌套表单。请注意,表单路由使用帮助器来定义它是否应该是创建或更新操作 <di

所以我想玩一个明星评级页面,在那里我有5个评级问题,你可以评级一次(创建)并在任何给定时间更新你的评级。评级表单是ajaxified的,但问题是表单元素在提交后仍然是一个Create方法,而不是update方法

我遵循了一个非常酷的教程,但是表单更新为正确的方法时缺少了一个部分

这是密码

我有一个部分
rating\u questions/\u quick\u form.html.erb中的表单,每个评级表单都有一个嵌套表单。请注意,表单路由使用帮助器来定义它是否应该是创建或更新操作

<div class="rating_questions">
    <% @rating_questions.each do |rating_question| %>
        <%= render partial: "rating_questions/rating_form", :locals => {:rating_question => rating_question} %>
    <% end %>
</div>
然后在我的
create.js.erb
中,我添加了一行代码,用部分

$('#<%= params[:temp_id] %>').replaceWith("<%= j render(partial: 'rating_questions/rating_form', locals: {:rating_question => @rating_question}) %>");
我的
ratings\u controller.rb
调用
create.js.erb
update.js.erb

def create
    @rating_question = RatingQuestion.find_by_id(params[:rating_question_id])
    @rating = Rating.new(params[:rating])
    @rating.user_id = current_user.id
    if @rating.save
      respond_to do |format|
        format.html { redirect_to rating_questions_path, :notice => "Your rating has been saved"}
        format.js
      end
    end
  end

  def update
    @rating_question = RatingQuestion.find_by_id(params[:rating_question_id])
    @rating = current_user.ratings.find_by_rating_question_id(@rating_question.id)
    if @rating.update_attributes(params[:rating])
      respond_to do |format|
        format.html { redirect_to rating_questions_path, :notice => "Your rating has been updated"}
        format.js
      end
    end
  end
显然,我只想更新刚刚提交的表单,而不是其他表单。 您知道如何在create.js.erb和update.js.erb中使用Javascript以正确的方法重新加载表单吗

多谢各位

编辑~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ (请参见上面的编辑)

我采纳了您的建议,将随机id添加到表单中,并更改了create.js.erb,但遇到了以下问题:

1) 在评级表被替换后,Javascript不再适用于该部分

这也是明星动态互动的咖啡脚本(实际上是无线电标签的形式)

编辑2~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 更新操作正在提交所有表单的事实已更正。

如果我没弄错的话

1。将生成的ID作为隐藏字段添加到表单中
该ID实际上不必是模型的虚拟属性,但可以是。另一个选项是将其置于质量分配数组之外,例如
params[:controller]
也是

示例:
。有关创建随机字符串的其他可能性,请参阅

还要确保表单(或在表单部分中呈现的第一个元素)将生成的随机字符串作为
id
data-
属性,以便在下一步中无需使用复杂的选择器即可访问它

2。更新您的create.js.erb
我假设您的创建操作中的
format.js
传递给
create.js.erb
。因此,在这里,您通过搜索提交时传递的临时id,将整个表单替换为一个新表单

示例:
$('#')。替换为(''

确保不要忽略它,因为它会对呈现的表单进行编码,以便在javascript中保存使用。当您呈现您的常用表单时,create操作完成了它的常规业务,现在还用一个新的呈现表单替换了表单,其中自动调用了“update”操作(路由中常见的rails“魔术”功能,就像您呈现另一个常用的编辑表单一样)

Javascript

在评级表被替换后,Javascript不再适用于该部分

当然不是。您正在将事件绑定到文档加载时的特定元素。之后插入的元素(通过创建/更新)是新添加的,因此没有该事件绑定,因为它们在事件绑定发生时不可用

因为,您需要将代码绑定到一个容器,该容器在js修改过程中是持久的。假设您的create.js只更新/替换
#rating_questions_container
中的元素,您需要将js重写为例如

$('#rating_questions_container').on('click', 'form.rating_ballot > label', function(e) {
  # code
});
  • $(“#评级_问题_容器”)
    是页面上的“持久”容器,可以捕获事件
  • .on('click'、'form.rating\u ballot>label'
    监视与第二个参数中的选择器匹配的元素上的单击事件,此处为
    form.rating\u ballot>label

这允许在
#rating_questions\u container
中动态附加/删除DOM节点,而不会丢失事件侦听器。

您好,谢谢您的快速回答,我想我的问题不是很清楚,分为两部分。如果我理解正确,随机id将帮助定义我希望更新的特定表单?这将肯定会有帮助,因为我有5个类似的表单。在使用Ajax深入挖掘之后,当它重新加载表单时,它不会使用helper方法
rating\u ballot
,该方法定义表单的路径
rating\u questions/1/ratings\35; create
rating\u questions/1/ratings/1#update
。我将尝试您的解决方案,看看它是否能解决问题这是我问题的一半:)是的,这就是随机id的意图。我看到了你的助手,这应该可以工作,因为你传递了一个包含两个对象的数组来构建路径。您只需要将表单放入一个分部,该分部可以同时处理
创建
更新
,现在应该是这样。因此,我按照您的建议进行了操作,但遇到了进一步的问题。1) 当我提交一个评分(无论是创建还是更新)时,它会为他们重新加载部分评分。2) 重新加载分部后,不再使用Coffescript文件中的jQuery。在我的原始帖子中查看我的编辑。更新我的答案以解决您的javascript问题。但我不明白你的第一个问题;你想更新部分,是吗?因为这会更新表单标记及其内部的所有内容,这是正常工作的update-form所必需的。好吧,这有点疯狂,但我结束了在所有地方添加.on()函数。现在一切都好了!非常感谢你,普德斯特勒!(由于某种原因,我必须等一个小时才能给赏金-。-)
def create
    @rating_question = RatingQuestion.find_by_id(params[:rating_question_id])
    @rating = Rating.new(params[:rating])
    @rating.user_id = current_user.id
    if @rating.save
      respond_to do |format|
        format.html { redirect_to rating_questions_path, :notice => "Your rating has been saved"}
        format.js
      end
    end
  end

  def update
    @rating_question = RatingQuestion.find_by_id(params[:rating_question_id])
    @rating = current_user.ratings.find_by_rating_question_id(@rating_question.id)
    if @rating.update_attributes(params[:rating])
      respond_to do |format|
        format.html { redirect_to rating_questions_path, :notice => "Your rating has been updated"}
        format.js
      end
    end
  end
$ ->
   # Add the "Bright class" to the stars for each checked radio button before the document is ready.
   $("form.rating_ballot").each ->
      checkedId = undefined
      checkedId = $(this).find("input:checked").attr("id")
      $(this).find("label[for=" + checkedId + "]").prevAll().andSelf().addClass "bright"

$(document).ready ->
   # makes stars glow on hover.
   $("form.rating_ballot > label").hover (-> # mouseover
      $(this).prevAll().andSelf().addClass "glow"
   ), -> # mouseout
      $(this).siblings().andSelf().removeClass "glow"

   # makes stars stay glowing after click.
   $("form.rating_ballot > label").click ->
      $(this).siblings().removeClass "bright"
      $(this).prevAll().andSelf().addClass "bright"

   # Submits the form (saves data) after user makes a change.
   $(".rating_ballot").change ->
      $(this).submit()
$('#rating_questions_container').on('click', 'form.rating_ballot > label', function(e) {
  # code
});