我最近尝试使用 petermac.com 上的本教程在我的应用程序中实现级联下拉菜单:http ://www.petermac.com/rails-3-jquery-and-multi-select-dependencies/
本教程主要讨论了做一个级联下拉菜单,其中每个下拉框都是一个单独的部分,并且在父选择更改时加载一个 jQuery onChange 事件。
现在我让这个工作没有问题。但实际上我的选择框之间的关系相当复杂。
因此,表单 I 属于名为 AuditFunction 的模型,顾名思义,用于审计。每个审计都有一个源和一个目标,可以通过几个命令进行比较。通过 3 个选择框选择源和目标。第一个框选择字段所在的数据库类型。第二个框选择表,然后第三个框选择字段。由于字段框可以包含数千个选项,我尝试实现级联下拉菜单,以使用户更容易选择字段。
为了给您一个概览,这就是我的操作:
# new.html.erb
<%= simple_form_for @audit_function do |f| %>
<%= f.input :database_1, :as => :select, :collection => @databases, :include_blank => true %>
<%= render :partial => 'databases_1' %>
<%= render :partial => 'fields_1' %>
<%= f.input :database_2, :as => :select, :collection => @databases, :include_blank => true %>
<%= render :partial => 'databases_2' %>
<%= render :partial => 'fields_2' %>
<% end %>
用于此的 javascript 如下所示:
# jQuery
<script type='text/javascript' charset='utf-8'>
jQuery(function($) {
// when the #country field changes
$("#audit_function_database_1").change(function() {
var database_1 = $('select#audit_function_database_1 :selected').val();
if(database_1 == "") database_1="0";
jQuery.get('/audit_functions/update_database_1_id_select/' + database_1, function(data){
$("#database_1_id").html(data);
})
return false;
});
})
</script>
<script type='text/javascript' charset='utf-8'>
jQuery(function($) {
// when the #country field changes
$("#audit_function_database_2").change(function() {
var database_2 = $('select#audit_function_database_2 :selected').val();
if(database_2 == "") database_2="0";
jQuery.get('/audit_functions/update_database_2_id_select/' + database_2, function(data){
$("#database_2_id").html(data);
})
return false;
});
})
现在我只向您展示 database_1_id 和 field_1_id 的部分内容,但它们看起来与数据库和字段 2 相同。
# _databases_1.html.erb
<script type="text/javascript">
jQuery(function($) {
$("#audit_function_database_1_id").change(function() {
var database_1_id = $('select#audit_function_database_1_id :selected').val();
if(database_1_id == "") database_1_id="0";
jQuery.get("/audit_functions/update_field_1_id_select/" + ("<%= params[:id] %>_" + database_1_id), function(data){
$("#field_1_id").html(data);
})
return false;
});
})
</script>
<%= simple_form_for "audit_function" do |f| %>
<% if params[:id] %>
<% if params[:id] == "imp" %>
<%= f.input :database_1_id, collection: AdOriTbl.all.order(ori_filename: :asc).collect{ |a| [a.ori_filename,a.id]} %>
<% elsif params[:id] == "ori" %>
<%= f.input :database_1_id, collection: AdOriTbl.all.order(otb_filename: :asc).collect{ |a| [a.otb_filename,a.id]} %>
<% elsif params[:id] == "mod" %>
<%= f.input :database_1_id, collection: AdQryMod.all.order(qry_mod_text: :asc).collect{ |a| [a.qry_mod_text,a.id]} %>
<% end %>
<% end %>
<% end %>
现在包含目标字段的文件。
# _fields_1.html.erb
<%= simple_form_for "audit_function" do |f| %>
<% if params[:id] %>
<% if params[:id].gsub(/_{1}\d{1,}\z/, "") == " mod " %>
<%= f.input :field_1_id, collection: AdQryFld.where(ad_qry_mod_id: params[:id].gsub(/\A\w{1,}_{1}/, "").to_i).order(order_id: :asc).collect{ |f| [f.qry_field_text,f.id]} %>
<% else %>
<%= f.input :field_1_id, collection: AdOriFld.where(ad_ori_tbl_id: params[:id].gsub(/\A\w{1,}_{1}/, "").to_i).order(id: :asc).collect{ |f| [f.otb_colhdg,f.id]} %>
<% end %>
<% end %>
<% end %>
然后控制器包含在 javascripts 中触发的所有操作:
# audit_function_conroller.rb
def new
authorize! :new, :audit_functions
@audit_function = AuditFunction.new
@functions = [[I18n.t("text sum"),"sum"],[I18n.t("text quantity"),"quantity"],[I18n.t("text largest_value"),"largest_value"],[I18n.t("text smallest_value"),"smallest_value"]]
@databases = [[I18n.t("text original_database"),"imp"],[I18n.t("text archive_database"),"ori"],[I18n.t("text query_database"),"mod"]]
end
def update_database_1_id_select
if params[:id] == "mod"
type = "mod"
elsif params[:id] == "ori"
type = "ori"
elsif params[:id] == "imp"
type = "imp"
end
render partial: "databases_1", id: type
end
def update_field_1_id_select
type = params[:id]
render partial: "fields_1", id: type
end
现在,尽管所有这些看起来都很混乱,但好处是它完成了工作。为了澄清我的 MVC,这些是关系:
AdOriTbl has_many AdOriFlds
AdOriFld belongs_to AdOriTbl
AdQryMod has_many AdQryFlds
AdQryFld belongs_to AdQryMod
我希望这些名字在阅读本文时不会打扰您。
现在让我们回到问题上来:
正如我所说,这段代码适用于创建一个新对象,并且一切都被选中。但是当我尝试编辑一个对象时,只有具有数据库类型(database_1 和 database_2)的字段被填充。数据库 ID 的选择框不会呈现,而字段的框会呈现。但是所有四个 ID 字段都是空的。
现在我已经尝试用一个基本上看起来与我已经拥有的类似的 jQuery 手动填充这些框,但是我没有触发 onChange,而是在我的 audit_function 有一个 database_id 并呈现选择框并用它填充它时触发它根据 database_id 的值。这也有效。
问题是我不能使用 field_id 执行此操作,因为在触发字段的 jQuery 的部分 database_1_id 中,我手头没有 @audit_function 对象,而且它似乎干扰了其他 javascripts .
除此之外,我还想认为有更好的方法来做到这一点,然后是我的方式。但是我已经尝试了其他教程和方法,当您没有直接的 Country-State-City 关系时,它们要么不起作用,要么在编辑时不起作用。
因此,任何帮助将不胜感激。谢谢!