所以我想玩星级评分页面,我有5个评分问题,您可以在任何给定时间评分一次(创建)并更新您的评分。评级表是ajaxified但问题是表单元素在提交后保留为Create方法而不是更新方法。
我遵循eighty-b的一个非常酷的教程,但是有一部分缺少关于正在更新为正确方法的表单。
这是代码
我在部分rating_questions/_quick_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>
rating_form.html.erb
部分
# EDIT: I added the temporary random id in an instance variable to make sure the form id and hidden_field have the same reference
<% @rand_id = SecureRandom.hex %>
<%= form_for(rating_ballot(rating_question), :remote => true, :html => { :class => 'rating_ballot', :id => @rand_id}) do |f| %>
<div class="rq"><%= rating_question.title %></div>
<%= hidden_field_tag :temp_id, @rand_id %>
<%= f.label("value_#{rating_question.id}_1", content_tag(:span, '1'), {:class => "rating", :id => "1"}) %>
<%= radio_button_tag("rating[value]", 1, current_user_rating(rating_question) == 1, :class => 'radio_button', :id => "rating_value_#{rating_question.id}_1") %>
... (the other rating radio buttons) ...
<%= f.hidden_field("rating_question_id", :value => rating_question.id) %>
<%= f.submit :Submit, :id => "rating_submit" %>
<% end %>
然后在我的create.js.erb
中添加了一行以用部分
$('#<%= params[:temp_id] %>').replaceWith("<%= j render(partial: 'rating_questions/rating_form', locals: {:rating_question => @rating_question}) %>");
用于定义表单应该是创建还是更新的辅助方法(如果存在现有记录)
def rating_ballot(rating_question)
if @rating = current_user.ratings.find_by_rating_question_id(rating_question.id)
[rating_question, @rating]
else
[rating_question, current_user.ratings.new]
end
end
def current_user_rating(rating_question)
if @rating = current_user.ratings.find_by_rating_question_id(rating_question.id)
@rating.value
else
"N/A"
end
end
以及要求ratings_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不再适用于该部分。
这里还有用于星星动态交互的咖啡脚本(实际上是形式的无线电标签)
$ ->
# 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()
编辑2 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 〜 更新操作提交所有表单的事实已得到纠正。
答案 0 :(得分:3)
如果我说对了你......
<强> 1。将生成的ID作为隐藏字段添加到表单
此ID实际上不一定是您的模型的虚拟属性,但可以。另一种选择是将它放在质量分配数组之外,例如也是params[:controller]
。
示例:<%= hidden_field_tag :temporary_id, SecureRandom.hex %>
。有关创建随机字符串的其他可能性,请查看how-best-to-generate-a-random-string-in-ruby 。
还要确保您的表单(或在表单部分中呈现的第一个元素)将生成的随机字符串作为id
或data-
属性,这样您就可以在不使用复杂的情况下访问它选择器在下一步。
<强> 2。更新您的create.js.erb
我假设您的创建操作中的format.js
会转到create.js.erb
。所以在那里,你用一个新表格替换整个表单,通过搜索传递提交的临时id。
示例:$('#<random_id_of_your_form>').replaceWith('<%= j render(partial: 'form', locals: {...}) %>');
请务必不要忽略the j
helper,因为它会对您呈现的表单进行编码,以便在javascript中保存。当您渲染通常的表单时,创建操作会执行其常规业务,现在还会使用新的呈现方式替换表单,自动调用“更新”操作(路由中常见的“魔术”内容,即就像你要渲染另一种常用的编辑形式一样。)
Javascript
更换评级表后,Javascript将不再适用于该部分。
当然不是。您将事件绑定到文档加载的特定元素。之后插入的元素(通过创建/更新)是新添加的,因此没有该事件绑定,因为它们在发生事件绑定时不可用。
从events are "bubbling"开始,您需要将代码绑定到一个在js修改中持久的容器。让我们说你的create.js只更新/替换#rating_questions_container
中的元素,你需要将js重写为例如
$('#rating_questions_container').on('click', 'form.rating_ballot > label', function(e) {
# code
});
$('#rating_questions_container')
是您网页上的“持久”容器,可以捕获事件.on('click', 'form.rating_ballot > label'
监视与第二个参数中的选择器匹配的元素的点击事件,此处为form.rating_ballot > label
。 这允许在#rating_questions_container
内动态附加/删除DOM节点,而不会丢失事件侦听器。