AJAX update of accepts_nested_attributes_for partials

删除回忆录丶 提交于 2019-12-02 05:45:59

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| %>
<div id="incident_category_select">
<%= render :partial => 'category_select', :locals => {:incident_form => this_form } %>
</div>
<% 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.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!