2013-11-01 38 views
0

我最近嘗試實現級聯下拉到我這個教程petermac.com應用:http://www.petermac.com/rails-3-jquery-and-multi-select-dependencies/複雜級聯下拉列表將不會在編輯表單工作

本教程基本上是關於做一個級聯下拉列表,在這裏舉行會談每個下拉框都是一個單獨的部分,並在父級選擇更改時使用jQuery onChange事件加載。

現在我得到了這個工作沒有問題。但實際上我的選擇框之間的關係相當複雜。

因此,表單我屬於名爲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 %> 

然後控制器包含在Java腳本觸發的所有操作:

# 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來做這件事,因爲在部分database_1_id中,這些字段的jQuery被觸發,我手邊沒有@audit_function對象,而且它似乎干涉與其他JavaScripts。

除此之外,我還想認爲有更好的方式來做到這一點,然後我的方式。但是我已經嘗試了其他的教程和方法,當你沒有直接的國家 - 城市 - 城市關係或者編輯時他們不工作時,他們要麼不工作。

所以,任何幫助將非常感激。謝謝!

回答

0

我把下面的教程爲模板,重寫我的級聯下拉菜單:

http://homeonrails.blogspot.de/2012/01/rails-31-linked-dropdown-cascading.html

所以,現在我把所有不同的模型轉換成一個陣列,並通過附加名稱到類過濾它,區分不僅通過身份證,而且通過名稱。另外jQuery插件chainedTo使代碼更加可讀。

因此,控制器現在看起來是這樣的:

@types_for_dropdown = [[I18n.t("text archive_database"),"ori"],[I18n.t("text query_database"),"mod"]] 

@tables_for_dropdown = [] 
@ad_qry_mods = AdQryMod.all 
@ad_qry_mods.each do |i| 
    @tables_for_dropdown = @tables_for_dropdown << [i.qry_mod_text,"mod#{i.id}",{:class => "mod"}] 
end 
@ad_ori_tbls = AdOriTbl.all 
@ad_ori_tbls.each do |i| 
    @tables_for_dropdown = @tables_for_dropdown << [i.otb_filename,"ori#{i.id}",{:class => "ori"}] 
end 

@fields_for_dropdown = [] 
@ad_qry_flds = AdQryFld.all 
@ad_qry_flds.each do |i| 
    @fields_for_dropdown = @fields_for_dropdown << [i.qry_fieldname,i.id,{:class => "mod#{i.ad_qry_mod_id}"}] 
end 
@ad_ori_flds = AdOriFld.all 
@ad_ori_flds.each do |i| 
    @fields_for_dropdown = @fields_for_dropdown << [i.otb_fieldname,i.id,{:class => "ori#{i.ad_ori_tbl_id}"}] 
end 

而且形式如下:

<%= content_for :head do %> 
<script> 
$(document).ready(function(){ 
$('select#audit_function_database_1_id').chainedTo('select#audit_function_database_1'); 
$('select#audit_function_field_1_id').chainedTo('select#audit_function_database_1_id'); 
$('select#audit_function_database_2_id').chainedTo('select#audit_function_database_2'); 
$('select#audit_function_field_2_id').chainedTo('select#audit_function_database_2_id'); 
}); 
</script> 
<% end %> 
<div class="grid-6-12"> 
    <%= f.input :database_1, label: I18n.t("field_label audit_function database_1"), hint: I18n.t("field_hint audit_function database_1"), as: :select, collection: @types_for_dropdown, include_blank: true %> 
</div> 
<div class="grid-6-12"> 
    <%= f.input :database_2, label: I18n.t("field_label audit_function database_2"), hint: I18n.t("field_hint audit_function database_2"), as: :select, collection: @types_for_dropdown, include_blank: true %> 
</div> 
<div class="grid-6-12"> 
    <%= f.input :database_1_id, label: I18n.t("field_label audit_function database_1_id"), hint: I18n.t("field_hint audit_function database_1_id"), as: :select, collection: @tables_for_dropdown, include_blank: true %> 
</div> 
<div class="grid-6-12"> 
    <%= f.input :database_2_id, label: I18n.t("field_label audit_function database_2_id"), hint: I18n.t("field_hint audit_function database_2_id"), as: :select, collection: @tables_for_dropdown, include_blank: true %> 
</div> 
<div class="grid-6-12"> 
    <%= f.input :field_1_id, label: I18n.t("field_label audit_function field_1_id"), hint: I18n.t("field_hint audit_function field_1_id"), as: :select, collection: @fields_for_dropdown, include_blank: true %> 
</div> 
<div class="grid-6-12"> 
    <%= f.input :field_2_id, label: I18n.t("field_label audit_function field_2_id"), hint: I18n.t("field_hint audit_function field_2_id"), as: :select, collection: @fields_for_dropdown, include_blank: true %> 
</div> 

這確實是一個很好的解決方案,我可以推薦給大家!