我的情况是,联系人有多个潜在客户,并且潜在客户属于个人资料。我成功地渲染了表格:
# _form.html.erb
<%= form_for @lead do |f| %>
<%= f.fields_for :contact do |builder| %>
<%= render "contact_fields", :f => builder %>
<%= render "leads_field", f: f %>
<% end %>
<% end %>
# lead_field.html.erb
<%= f.select :practice_type, PRACTICE_TYPES.collect {|type| [ type, type ] }
<%= f.fields_for :practice do |builder| %>
<%= render "#{@practice.class.name.underscore}_field", :f => builder %>
<% end %>
上面的页面加载工作正常。但是,用户可以从下拉菜单中选择练习,然后发送ajax请求以重新填充表单,从而构建与该练习的关联:
$('#lead_practice_type').change(function() {
$.ajax({
url: "/leads/new",
data: {
profile_type : $(this).val()
},
dataType: "script"
});
});
错误发生在new.js.erb:
$("#form_holder").html("<%= escape_javascript(render(:partial => "leads_field"))%>");
我想只渲染那部分(如果我渲染整个表单,那么他们所有的联系信息都将被删除。)。但由于该部分包含一个局部f变量,它会爆炸:
NameError - undefined local variable or method `f'
我想维护对象之间的关系,但也只更新那个部分。但似乎我不能通过new.js.erb脚本来实现它,因为当它呈现部分时,没有传递局部变量'f'。
还有另一种方法可以达到我的目的吗?
答案 0 :(得分:0)
我发现这个问题很难在两个方面解决。首先,您无法从控制器操作和javascript中识别表单构建器。其次,尽管我对railscasts剧集http://railscasts.com/episodes/196-nested-model-form-revised?view=comments非常熟悉,但在那一集中他知道fields_for在编译时生成,因此他将标记隐藏在链接的数据字段中。不幸的是,在我的情况下,我不知道用户想要的fields_for直到运行时(当浏览器加载并且用户选择一个选项时)。
我还意识到fields_for对于保持表单提交的良好关联很重要,这样创建操作就可以了:保存父资源并保存其关联。
我能想出的最佳解决方案如下:
1)使用fields_for创建所有多态关联,并通过选择表单字段隐藏用户不想要的关联:
# template
<div id="runtime-profile">
<% Lead::TYPES.each_with_index do |association, index| %>
<div id="profile_<%= association %>">
<fieldset class="field-border">
<legend class="field-border"><%= association.underscore %></legend>
<%= f.fields_for :practice, build_builder_association(f, association) do |builder| %>
<%= render "#{builder.object.class.name.underscore}_field", :f => builder %>
<% end %>
</div>
<% end %>
</div>
# helper
def build_builder_association(f, association)
f.object.practice_type = association
f.object.build_practice({})
end
使用Javascript根据从下拉列表中选择的选项隐藏和显示模板,然后在提交表单时,从DOM中删除隐藏的元素:
$("#new_lead").submit(function(){
$("[id^='profile_']:hidden").remove();
})
这创造了我想要的原始所需行为。但是,解决方案远非干净,欢迎任何更好的建议。