Note that there are some explanatory texts on larger screens.

plurals
  1. POAJAX update of accepts_nested_attributes_for partials
    text
    copied!<p>My current working environment is Rails <strong>2.3.8</strong> (various reasons why my company hasn't moved to Rails 3). I'm trying to update elements of a multi-model form via AJAX calls - the idea being to replace certain dropdowns depending on how the user selects or fills in other fields.</p> <p>I have previously managed to get this working by using non-form based partials - the problem I have now is to reproduce the AJAX updating of the select dropdowns when the partials are based around form_for and fields_for.</p> <p>Sorry for the following wall of text - i've tried to cut it down as much as possible (the code itself does work on my test site).</p> <p>How do I generate the form builder elements in the Outbreak controller and then pass this to the category partial to take the place of incident_form?</p> <p>Any pointers would be great :D </p> <p>Models</p> <pre><code>class Outbreak &lt; ActiveRecord::Base has_many :incidents, :dependent =&gt; :destroy has_many :locations, :through =&gt; :incidents accepts_nested_attributes_for :locations, :allow_destroy =&gt; true, :reject_if =&gt; :all_blank accepts_nested_attributes_for :incidents, :allow_destroy =&gt; true, :reject_if =&gt; :all_blank end class Incident &lt; ActiveRecord::Base belongs_to :outbreak belongs_to :location belongs_to :category belongs_to :subcategory belongs_to :subtype end class Location &lt; ActiveRecord::Base has_many :incidents, :dependent =&gt; :destroy has_many :outbreaks, :thorugh =&gt; incidents end </code></pre> <p>Views</p> <p>_form</p> <pre><code>&lt;% form_for(@outbreak, :html =&gt; {:multipart =&gt; true}) do |form| %&gt; &lt;%= render :partial =&gt; 'outbreak_type_select', :locals =&gt; {:outbreak_types =&gt; @outbreak_types, :f =&gt; form } %&gt; &lt;% form.fields_for :incidents do |incident_form| %&gt; &lt;%= render :partial =&gt; 'category_select', :locals =&gt; {:categories =&gt; @categories, :incident_form =&gt; incident_form} %&gt; &lt;%= render :partial =&gt; 'subcategory_select', :locals =&gt; { :subcategories =&gt; @subcategories, :incident_form =&gt; incident_form } %&gt; &lt;% end %&gt; &lt;% end %&gt; </code></pre> <p>_outbreak_type_select</p> <pre><code>&lt;% with_str = "'outbreak_type=' + value " %&gt; &lt;% if @outbreak.id %&gt; &lt;% with_str &lt;&lt; "+ '&amp;id=' + #{outbreak.id}" %&gt; &lt;% end %&gt; &lt;%= f.collection_select(:outbreak_type, @outbreak_types, :property_value, :property_value, {}, {:onchange =&gt; "#{remote_function(:url =&gt; { :action =&gt; "update_select_menus"}, :with =&gt; with_str)}"} ) %&gt; </code></pre> <p>_category_select</p> <p><strong>After calling update_select_menus how to generate the incident_form</strong></p> <pre><code>&lt;%= incident_form.collection_select( :category_id, @categories, :id, :name, {:prompt =&gt; "Select a category"}, {:onchange =&gt; "#{remote_function(:url =&gt; { :action =&gt; "update_subcategory"}, :with =&gt; "'category_id='+value")}"}) %&gt; </code></pre> <p>RJS</p> <pre><code> begin page.replace_html 'outbreak_transmission_div', :partial =&gt; 'outbreaks/transmission_mode_select', :locals =&gt; {:transmission_modes =&gt; @transmission_modes } rescue page.insert_html :bottom, 'ajax_error', '&lt;p&gt;Error :: transmission modes update select&lt;/p&gt;' page.show 'ajax_error' end begin page.replace_html 'incident_category_select', :partial =&gt; 'outbreaks/category_select', :locals =&gt; { :categories =&gt; @categories } rescue page.insert_html :bottom, 'ajax_error', '&lt;p&gt;Error :: incident category update select&lt;/p&gt;' page.show 'ajax_error' end </code></pre> <p>Controllers</p> <p>Outbreak</p> <pre><code> def new @outbreak = Outbreak.new @outbreak.incidents.build @outbreak.locations.build #just the contents for the dropdowns @categories = Category.find(:all, :conditions =&gt; {:outbreak_type =&gt; "FOODBORNE"}, :order =&gt; "outbreak_type ASC") @subcategories = Subcategory.find(:all, :order =&gt; "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:" &lt;&lt; @outbreak_type @transmission_modes = Property.find(:all, :conditions =&gt; {:field =&gt; ob_type_query}) ob_type_query = "INVESTIGATIONS:CATEGORY:" &lt;&lt; @outbreak_type @sample_types = Property.find(:all, :conditions =&gt; {:field =&gt; ob_type_query}) @categories = Category.find(:all, :conditions =&gt; { :outbreak_type =&gt; "FOODBORNE"}) @subcategories = Subcategory.find(:all, :conditions =&gt; { :category_id =&gt; @categories.first.id}) @subtypes = Subtype.find(:all, :conditions =&gt; { :subcategory_id =&gt; @subcategories.first.id}) elsif @outbreak_type == "NON-FOODBORNE" ob_type_query = "OUTBREAKS:TRANSMISSION_MODE:" &lt;&lt; @outbreak_type @transmission_modes = Property.find(:all, :conditions =&gt; {:field =&gt; ob_type_query}) ob_type_query = "INVESTIGATIONS:CATEGORY:" &lt;&lt; @outbreak_type @sample_types = Property.find(:all, :conditions =&gt; {:field =&gt; ob_type_query}) @categories = Category.find(:all, :conditions =&gt; { :outbreak_type =&gt; "NON-FOODBORNE"}) @subcategories = Subcategory.find(:all, :conditions =&gt; { :category_id =&gt; @categories.first.id}) @subtypes = Subtype.find(:all, :conditions =&gt; { :subcategory_id =&gt; @subcategories.first.id}) end respond_to do |format| format.html format.js end end </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload