0

我使用​​通過使用jQuery的JavaScript動態添加和刪除嵌套的模型字段。將變量值形式的js函數傳遞給rails視圖(動態選擇)

有4種型號:client,c_person;項目,p_person。和一對多的關聯:客戶有很多c_people,項目有很多p_people(這些是來自客戶端的人,但他們屬於項目)。

所以,我有以下問題:

當我使用在我看來helper方法「link_to_add_fields」,我需要通過另一個參數(current_client_id)那要看什麼客戶在選擇框中當前選定。

<!-- new.html.erb --> 
<p> 
<%= f.label :client_id %></br> 
<%= f.collection_select :client_id, Client.order("title"), :id, :title %> 
</p> 
<p> 
<%= f.fields_for :p_people do |builder| %> 
<%= render "p_person_fields", :f => builder %> 
<% end %> 
</p> 
<p><%= link_to_add_fields "Add Person", f, :p_people, current_client_id %></p> 

我需要動態改變的集合中的輔助方法@people變量,

# application_helper.rb 
def link_to_add_fields(name, f, association, current_client_id) 
    new_object = f.object.class.reflect_on_association(association).klass.new 
    @people = CPerson.where(:client_id => current_client_id).order(:name) unless current_client_id.blank? 
    fields = f.fields_for(association, new_object, :child_index => "new_#{association}") do |builder| 
     render(association.to_s.singularize + "_fields", :f => builder) 
    end 
    link_to_function(name, h("add_fields(this, \"#{association}\", \"#{escape_javascript(fields)}\")")) 
end 

,終於用它在部分:

<!-- _p_person_fields.html.erb --> 
<div class="fields"> 
<p> 
<%= f.collection_select :content, @people, :name, :name %> 
<%= f.hidden_field :_destroy %> 
<%= link_to_function "Remove", "remove_fields(this)" %> 
</p> 
</div> 

下面是簡單的JS功能獲取current_client_id值,但我不知道如何將它傳遞給我的視圖或幫助器方法。

// application.js 
function current_client_id() { 
var current_client_id = $("select#client_id :selected").val(); 
} 

我感謝您的幫助!也許有更好的解決方案?

回答

0

我不喜歡這件事的一件事是,你在視圖助手中使用邏輯,這真的屬於你的控制器。

也許更好的方法是使用current_client_id對控制器進行AJAX調用。然後,該控制器可以獲取@people對象,併發回一個js.erb模板,您可以在其中添加一個局部視圖。或者它可以發送一個JSON對象,並且處理程序到您的AJAX調用將創建添加到DOM的新元素。

0

我發現了將人員分配給項目的更好方法 - 使用多個選擇選項。這允許不使用嵌套模型字段。

1.使用has_and_belongs_to_many兩個模型之間的關聯:c_person和項目。

2.創建連接表:

class CreateCPeopleProjects < ActiveRecord::Migration 
    def self.up 
    create_table :c_people_projects, :id => false do |t| 
     t.references :project 
     t.references :c_person 
    end 
    end 

    def self.down 
    drop_table :c_people_projects 
    end 
end 

3.修改new.html.erb和部分。

<!-- new.html.erb --> 
<p> 
<%= f.label :client_id, "Client" %><br /> 
<%= f.collection_select :client_id, @clients, :id, :title %> 
</p> 
<div id="people"> 
<%= render "c_people" %> 
</div> 

<!-- _c_people.html.erb --> 
<p> 
<%= fields_for :project do |f| %> 
<% if @update_people.blank? %> 
<%= f.collection_select :c_person_ids, @people, :id, :name, {:selected => @project.c_person_ids}, {:multiple => true, :name => "project[c_person_ids][]"} %> 
<% else %> 
<%= f.collection_select :c_person_ids, @update_people, :id, :name, {}, {:multiple => true, :name => "project[c_person_ids][]"} %> 
<% end %> 
<% end %> 
</p> 

4.添加js函數以獲取當前客戶端id值,將其發送到projects_controller並用新集合替換部分。

jQuery(function($) { 
$(function() { 
    $("#project_client_id").change(function() { 
    var client_id = $("select#project_client_id :selected").val(); 
    if (client_id == "") {client_id = "0";} 
    $.get("/projects/update_people/" + client_id, function(data){ 
    $("#people").html(data); 
    }) 
    return false; 
    }); 
}); 
}) 

5.Add方法projects_controller動態地改變集合的人。還有一行更新操作(用於更新零對象)。

def update 
    @project = Project.find(params[:id]) 
    params[:project][:c_person_ids] ||= [] 

    respond_to do |format| 
     if @project.update_attributes(params[:project]) 
     format.html { redirect_to(@project, :notice => 'Project was successfully updated.') } 
     format.xml { head :ok } 
     else 
     format.html { render :action => "edit" } 
     format.xml { render :xml => @project.errors, :status => :unprocessable_entity } 
     end 
    end 
    end 

    def update_people 
    @update_people = CPerson.where(:client_id => params[:id]).order(:name) unless params[:id].blank? 
    render :partial => "c_people" 
    end 

6.Don't忘記路線:match "/projects/update_people/:id" => "projects#update_people"

0

如果您正在使用的Rails 3,那麼你應該刪除 「H(」 在application_helper。RB:

link_to_function(name, h("add_fields(this, \"#{association}\", \"#{escape_javascript(fields)}\")")) 

link_to_function(name, "add_fields(this, \"#{association}\", \"#{escape_javascript(fields)}\")")