gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-11-29 10:45:48 25 4
gpt4 key购买 nike

所以我想玩一个星级评分页面,我有 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.erbupdate.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 不再适用于该部分。

这里还有星星动态交互的coffee脚本(其实就是radio labels的形式)

$ ->
# 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 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~更正了更新操作提交所有表单的事实。

最佳答案

如果我没猜错的话......

<强>1。将生成的 ID 作为隐藏字段添加到您的表单中
这个 ID 不一定是模型的虚拟属性,但可以是。另一种选择是将它放在质量分配数组之外,例如 params[:controller]也是。

示例:<%= hidden_field_tag :temporary_id, SecureRandom.hex %> .有关创建随机字符串的其他可能性,请查看 how-best-to-generate-a-random-string-in-ruby .

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

<强>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 中保存使用。当您呈现您通常的表单时,创建操作执行其通常的业务,现在也用新呈现的表单替换表单,自动调用“更新”操作(路由中通常的 rails“魔术”东西,即是。就像你呈现另一个普通的编辑表单一样)。

Javascript

After the ratings forms are replaced, the Javascript no longer works on that partial.

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

events are "bubbling" ,您需要将您的代码绑定(bind)到一个容器,该容器在您的 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 节点而不会丢失事件监听器。

关于javascript - Rails/Ajax 将表单从创建更改为提交后更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19765256/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com