我在Rails中使用嵌套模型表单,其中包含一个问答应用程序,类似于Ryan Bates,在这里:http://railscasts.com/episodes/196-nested-model-form-revised。
现在,我想让问题排序,然后在show.html.erb中显示它们时保存它们的位置。
所以我的观点如下:
_form.html.erb:
<%= f.fields_for :questions do |builder| %>
<ul class='sortable'>
<%= render 'question_fields', f: builder %>
</ul>
<% end %>
<%= link_to_add_fields "Add Question", f, :questions %>
_question_fields.html.erb:
<li>
<%= f.label :content, "Question" %><br />
<%= f.text_area :content %><br />
<%= f.check_box :_destroy %>
<%= f.label :_destroy, "Remove Question" %>
</li>
我的jquery只是一个简单的:
$(".sortable").sortable();
帮助者是:
def link_to_add_fields(name, f, association)
new_object = f.object.send(association).klass.new
id = new_object.object_id
fields = f.fields_for(association, new_object, child_index: id) do |builder|
render(association.to_s.singularize + "_fields", f: builder)
end
link_to(name, '#', class: "add_fields", data: {id: id, fields: fields.gsub("\n", "")})
end
我发现了类似的关于通过Ajax保存的问题(使用Sortable的serialize()
),但我真的只是在寻找一种无需使用AJAX即可保存的解决方案。
答案 0 :(得分:3)
好的,您可以注意到,当您为问题呈现字段时:
questions
集合link_to_add_fields
方法每个问题表单构建器都有一个child_index
,它可以是问题的id本身,也可以是新创建的(但未保存的)问题对象的object_id
。这意味着您为特定问题添加的每个字段都嵌套在专用哈希中,允许您将具有相同名称的输入的不同值关联到每个问题。
所以你已经有一些与每个问题相关联的值......你应该做的是向question_fields
添加一个隐藏的输入字段来存储问题的位置:
f.hidden_field :position, class: 'question-position'
在您的javascript代码中,创建一个函数,用于设计可排序列表中每个问题的位置。这是它的样子(我没有测试过这段代码,但我相信它应该可行):
function refreshPositions()
{
$('.question-position').each(function() {
var idx = $(this).closest('li').index();
$(this).val(idx);
});
}
这将使用类question-position
遍历所有隐藏的输入,在可排序列表中找到其父<li>
的位置,并将位置分配给隐藏的字段值。这样做,您就可以获得与每个问题相关联的位置值。
将此函数与jQueryUI可排序事件create
和update
一起使用,以维护每个问题位置的最新值:
$(".sortable").sortable({
create: refreshPositions,
update: refreshPositions
});
(这是有效的,因为我们不期望给refreshPositions
任何参数,否则你需要为每个处理程序使用匿名函数并从那里调用refreshPositions
根据此设置,当您提交表单时,您现在将在Rails应用中收到一个问题,其中包含position
字段,您可以将其保存到Question
模型中,然后用于订购问题