1

Моя текущая рабочая среда Rails 2.3.8 (различные причины, по которым моя компания не переехала в Rails 3). Я пытаюсь обновить элементы многомодельной формы через вызовы AJAX - идея заключается в замене определенных выпадающих списков в зависимости от того, как пользователь выбирает или заполняет другие поля.AJAX обновление accepts_nested_attributes_for partials

Мне до этого удалось получить эту работу, используя частичные части, основанные на неформе. Проблема заключается в том, чтобы воспроизвести AJAX-обновление раскрывающихся списков выбора, когда частичные элементы основаны на form_for и fields_for.

Извините за следующую текстовую стену - я попытался как можно сократить ее (сам код работает на моем тестовом сайте).

Как создать элементы построителя формы в контроллере Outbreak, а затем передать это в категорию, частичную, чтобы заменить место инцидента_формы?

Все указатели было бы здорово: D

Модели

class Outbreak < ActiveRecord::Base 
     has_many :incidents, :dependent => :destroy 
     has_many :locations, :through => :incidents 

    accepts_nested_attributes_for :locations, :allow_destroy => true, :reject_if => :all_blank 
    accepts_nested_attributes_for :incidents, :allow_destroy => true, :reject_if => :all_blank 
end 

class Incident < ActiveRecord::Base 
    belongs_to :outbreak 
    belongs_to :location 
    belongs_to :category 
    belongs_to :subcategory 
    belongs_to :subtype 

end 

class Location < ActiveRecord::Base 
    has_many :incidents, :dependent => :destroy 
    has_many :outbreaks, :thorugh => incidents 
end 

Просмотров

_form

<% form_for(@outbreak, :html => {:multipart => true}) do |form| %> 

    <%= render :partial => 'outbreak_type_select', :locals => {:outbreak_types => @outbreak_types, :f => form } %> 
    <% form.fields_for :incidents do |incident_form| %> 
     <%= render :partial => 'category_select', :locals => {:categories => @categories, :incident_form => incident_form} %> 
     <%= render :partial => 'subcategory_select', :locals => { :subcategories => @subcategories, :incident_form => incident_form } %> 

    <% end %> 
<% end %> 

_outbreak_type_select

<% with_str = "'outbreak_type=' + value " %> 
<% if @outbreak.id %> 
<% with_str << "+ '&id=' + #{outbreak.id}" %> 
<% end %> 
<%= f.collection_select(:outbreak_type, @outbreak_types, :property_value, :property_value, {}, {:onchange => "#{remote_function(:url => { :action => "update_select_menus"}, :with => with_str)}"} ) %> 

_category_select

После вызова update_select_menus как генерировать incident_form

<%= incident_form.collection_select(:category_id, @categories, :id, :name, {:prompt => "Select a category"}, {:onchange => "#{remote_function(:url => { :action => "update_subcategory"}, :with => "'category_id='+value")}"}) %> 

RJS

begin 
    page.replace_html 'outbreak_transmission_div', :partial => 'outbreaks/transmission_mode_select', :locals => {:transmission_modes => @transmission_modes } 
    rescue 
    page.insert_html :bottom, 'ajax_error', '<p>Error :: transmission modes update select</p>' 
    page.show 'ajax_error' 
    end 
    begin 
    page.replace_html 'incident_category_select', :partial => 'outbreaks/category_select', :locals => { :categories => @categories } 
    rescue 
    page.insert_html :bottom, 'ajax_error', '<p>Error :: incident category update select</p>' 
    page.show 'ajax_error' 
    end 

Контроллеры

вспышках

def new 
     @outbreak = Outbreak.new 

     @outbreak.incidents.build 
     @outbreak.locations.build 

     #just the contents for the dropdowns 
     @categories = Category.find(:all, :conditions => {:outbreak_type => "FOODBORNE"}, :order => "outbreak_type ASC") 
     @subcategories = Subcategory.find(:all, :order => "category_id ASC") 

    end 

    def update_select_menus 
     @outbreak_type = params[:outbreak_type].strip 
     if params[:id] 
     @outbreak = Outbreak.find(params[:id]) 
     else 
     @outbreak = Outbreak.new 
     @outbreak.incidents.build 
       @outbreak.locations.build  
     end 

     if @outbreak_type == "FOODBORNE" 
      ob_type_query = "OUTBREAKS:TRANSMISSION_MODE:" << @outbreak_type 
      @transmission_modes = Property.find(:all, :conditions => {:field => ob_type_query}) 

      ob_type_query = "INVESTIGATIONS:CATEGORY:" << @outbreak_type 
      @sample_types = Property.find(:all, :conditions => {:field => ob_type_query}) 
      @categories = Category.find(:all, :conditions => { :outbreak_type => "FOODBORNE"}) 
      @subcategories = Subcategory.find(:all, :conditions => { :category_id => @categories.first.id}) 
      @subtypes = Subtype.find(:all, :conditions => { :subcategory_id => @subcategories.first.id}) 
     elsif @outbreak_type == "NON-FOODBORNE" 
      ob_type_query = "OUTBREAKS:TRANSMISSION_MODE:" << @outbreak_type 
      @transmission_modes = Property.find(:all, :conditions => {:field => ob_type_query}) 

      ob_type_query = "INVESTIGATIONS:CATEGORY:" << @outbreak_type 
      @sample_types = Property.find(:all, :conditions => {:field => ob_type_query}) 
      @categories = Category.find(:all, :conditions => { :outbreak_type => "NON-FOODBORNE"}) 
      @subcategories = Subcategory.find(:all, :conditions => { :category_id => @categories.first.id}) 
      @subtypes = Subtype.find(:all, :conditions => { :subcategory_id => @subcategories.first.id}) 
    end 

    respond_to do |format| 
      format.html 
      format.js 
     end 

    end 

ответ

1

Нашли работу вокруг, основанный на http://www.treibstofff.de/2009/07/12/ruby-on-rails-23-nested-attributes-with-ajax-support/

Это, вероятно, следует перейти в вспышках помощника (в вспышках контроллера атм)

def update_select_menus 
     @outbreak_type = params[:outbreak_type].strip 
     #next_child_index will only be used if 
     @next_child_index ? params[:next_child_index] : 0 
     if params[:id] 
     @outbreak = Outbreak.find(params[:id]) 
     else 
     @outbreak = Outbreak.new 
     @outbreak.risks.build 
     @outbreak.incidents.build 
     @outbreak.locations.build 

     end 

     if @outbreak_type == "FOODBORNE" 
      ob_type_query = "OUTBREAKS:TRANSMISSION_MODE:" << @outbreak_type 
      @transmission_modes = Property.find(:all, :conditions => {:field => ob_type_query}) 

      ob_type_query = "INVESTIGATIONS:CATEGORY:" << @outbreak_type 

      @sample_types = Property.find(:all, :conditions => {:field => ob_type_query}) 
      @categories = Category.find(:all, :conditions => { :outbreak_type => "FOODBORNE"}) 
      @subcategories = Subcategory.find(:all, :conditions => { :category_id => @categories.first.id}) 
      @subtypes = Subtype.find(:all, :conditions => { :subcategory_id => @subcategories.first.id}) 


     elsif @outbreak_type == "NON-FOODBORNE" 
      ob_type_query = "OUTBREAKS:TRANSMISSION_MODE:" << @outbreak_type 
      @transmission_modes = Property.find(:all, :conditions => {:field => ob_type_query}) 

      ob_type_query = "INVESTIGATIONS:CATEGORY:" << @outbreak_type 

      @sample_types = Property.find(:all, :conditions => {:field => ob_type_query}) 
      @categories = Category.find(:all, :conditions => { :outbreak_type => "NON-FOODBORNE"}) 
      @subcategories = Subcategory.find(:all, :conditions => { :category_id => @categories.first.id}) 
      @subtypes = Subtype.find(:all, :conditions => { :subcategory_id => @subcategories.first.id}) 
    end 

    @pathogen_types = Property.find(:all, :conditions => {:field => "PATHOGENS:CATEGORY"}) 
    @outbreak_types = Property.find(:all, :conditions => {:field => "OUTBREAKS:OUTBREAK_TYPE"}) 


    render :update do |page| 
     page.replace 'outbreak_transmission_div', :partial => 'transmission_mode_select_update' 
     page.replace 'incident_category_select', :partial => 'incident_category_select_update' 
     page.replace 'incident_subcategory_select', :partial => 'incident_subcategory_select_update' 
     page.replace 'incident_subtype_select', :partial => 'incident_subtype_select_update' 
    end  

    end 

В представлении о вспышках (хотя, так как это частичное связано с инцидентом так ли следует, скорее всего, перейти в эту точку зрения)

<% ActionView::Helpers::FormBuilder.new(:outbreak, @outbreak, @template, {}, proc{}).fields_for :incidents,{:child_index => @next_child_index} do |this_form| %> 
<div id="incident_category_select"> 
<%= render :partial => 'category_select', :locals => {:incident_form => this_form } %> 
</div> 
<% end %> 

ActionView :: Помощники :: FormBuilder используется для создания обязательные поля для формы. Более подробная информация приведена на веб-сайте.

Полученный индекс устанавливается с помощью переменной @next_child_index, который может быть передан в контроллер с помощью оригинального AJAX вызова (например, @next_child_index = 1, то полученное имя элемента формы будет вспышки [incidents_attributes] [1] [category_id]). Я не использовал это в этом примере, потому что, хотя в будущем я хочу, чтобы форма поддерживала более одного места для Outbreak для этого первоначального прогона, она просто примет одно местоположение - инцидент в каждой вспышке.

_category_select.erb частичная (в вспышках зрения атм)

<% with_str = "'category_id=' + value " %> 
<% if @outbreak.id %> 
<% with_str << "+ '&id=' + #{@outbreak.id}" %> 
<% end %> 
<%= incident_form.collection_select(:category_id, @categories, :id, :name, {:prompt => "Select a category"}, {:onchange => "#{remote_function(:url => { :action => "update_subcategory"}, :with => with_str)}"}) %> 

with_str это просто необязательно передать идентификатор Outbreak, если он существует в контроллер, чтобы найти запись о вспышках, чтобы произвести форму и если не создайте новый Outbreak и связанные с ним вложенные атрибуты, такие как инциденты и местоположения.

Должны быть более аккуратные способы сделать это - особенно FormHelper и передать идентификатор Outbreak через опциональную строку.

+0

Откуда вы взяли переменную @template? im пытается реализовать это, но у меня проблема с шаблоном [проверьте мой пост для получения дополнительной информации] (http://stackoverflow.com/questions/7272814/passing-actionviewhelpersformbuilder-to-a-partial) – jalagrange

+0

Think '@template '- это переменная по умолчанию, созданная приложением Rails 2.3. Если вы используете Rails 3>, тогда @template будет равен нулю, и вам, возможно, придется взглянуть на view_context http://stackoverflow.com/questions/3300582/rails-3-template-variable-inside-controllers-is- ноль – Pasted