AJAX update of accepts_nested_attributes_for partials

后端 未结 1 1190
耶瑟儿~
耶瑟儿~ 2021-01-23 22:51

My current working environment is Rails 2.3.8 (various reasons why my company hasn\'t moved to Rails 3). I\'m trying to update elements of a multi-model form vi

1条回答
  •  孤城傲影
    2021-01-23 23:20

    Found a work around based on http://www.treibstofff.de/2009/07/12/ruby-on-rails-23-nested-attributes-with-ajax-support/

    This should probably go in Outbreak helper (in Outbreak controller atm)

        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
    

    In the Outbreak view (although since this partial is related to Incident it should probably go in that view instead)

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

    The ActionView::Helpers::FormBuilder is used to produce the required fields_for form - The website article goes through this in more detail.

    The resulting index is set by the @next_child_index variable which can be passed to the controller by the original AJAX call (for example @next_child_index = 1, then the resulting form element name will be outbreak [incidents_attributes] [1] [category_id] ) - I haven't used this in this example because although in future I want the form to support more than one location per Outbreak for this initial run-through it will just accept a single Location - Incident per Outbreak.

    _category_select.erb partial (in Outbreak view atm)

    <% 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)}"}) %>
    

    The with_str is just to optionally pass the Outbreak id if it exists to the controller to find the Outbreak record to produce the form and if not to build a new Outbreak and associated nested attributes like Incidents and Locations.

    The must be neater ways of doing this - especially the FormHelper and passing the Outbreak id via the optional with string.

    0 讨论(0)
提交回复
热议问题