Dynamic drop-downs in a form_for using AJAX remote_function - Help

Hello -

I am fairly new to Ruby on Rails, but feel like I am learning quick. I have what seems to be a fairly unique issue as I cannot find much out there that describes what I'm seeing. Hopefully it's a very simple fix, and I simply can't see the forest through all the trees!

I am attempting to create 2 related drop-down lists in the same form_for, both using collection_select. On the first drop-down, I have an onChange "remote_function" call that I want to send an AJAX call to the controller and filter the list in the 2nd drop-down based on what was selected in the first. In the controller method, I then call page.replace_html to render a partial. In the partial is the "updated/filtered" 2nd collection_select drop- down list.

The remote_function works fine and calls the Controller method when the first drop-down changes. I am also able to pass the selected value to the method and filter the records returned. The problem occurs when the controller attempts to render the partial, I get the following error:

ActionView::TemplateError (undefined local variable or method `f' for #<ActionView::Base:0xb6e7b2f4>) on line #1 of app/views/listings/ _automodels.html.erb: <%= f.collection_select :model, @automodels, :model, :model, {:prompt => "-Select a Make First-"} %>

This leads me to believe that the "f" variable the rest of the fields in the form_for are using is not available to the newly-replaced "collection_select", but I'm not sure why?

If the partial contains a simple HTML <input> instead of the collection_select, the replace_html works fine.

Source code is worth 1,000 words, so here it is:

listings/new.html.erb

   1. <% form_for([@user, @listing]) do |f| %>    2. <%= f.error_messages %>    3. <p>    4. <%= f.label :make %><br />    5. <%= f.collection_select :make, @automakes, :make, :make, {:prompt => "-Select a Make-"}, {:onChange => remote_function(:url => {:action => 'get_automodels'}, :with => "'make=' + this.value")} %>    6. </p>    7. <p>    8. <%= f.label "Model:" %><br/>    9. <div id='automodelsdiv'>   10. <%= f.collection_select :model, @automodels, :model, :model, {:prompt => "-Select a Make First-"} %>   11. </div>   12. </p>   13. <p>   14. <%= f.submit 'Create' %>   15. </p>   16. <% end %>

listings_controller.rb

   1. def get_automodels    2. @automodels = Automodels.find_by_make(params[:make])    3. render :update do |page|    4. page.replace_html('automodelsdiv', :partial => 'automodels')    5. end    6. end

_automodels.html.erb

   1. <%= f.collection_select :model, @automodels, :model, :model, {:prompt => "-Select a Make First-"} %>

Because that f referred to a form builder object created by form_for. You're in a different scope to when you rendered the original form, in a different request, with a different instance of the controller, possibly on a different mongrel or even a different server. The form builder isn't going to magically appear.

Fred

Thanks Frederick for looking at my issue.

Apparently I don't have a full understanding of how the AJAX request interacts with (or I guess doesn't interact with) the form_for... So is the basic idea of what I'm attempting completely wrong or is there some slight modification I can do to pull it off? Basically, I have a form where I want to create a new listing record - but I want the fields to be restricted to values stored in the automodels Model in the database (and the model drop-down to be filtered based on the make selected). From what I've been reading, the best way to do the "dynamic select" is using AJAX. However, I guess the collection_selects are never inside a form in the examples I've read?

I'm open to any suggestions from the experts here - even if it means overhauling the whole thing... :slight_smile:

You could put each select in a partial then re-render it when coming back from the rjs with the updated select items.

Thanks Frederick for looking at my issue.

Apparently I don't have a full understanding of how the AJAX request interacts with (or I guess doesn't interact with) the form_for...

Forget about the ajaxness of it. If you had a page with a form and you followed a link from that page you wouldn't expect the form builder from the first page to be hanging around when you render the second page. If you want to use the form builder version of a helper you just need to create a new form builder for the template that gets rendered for the ajax request (you can use fields_for to create a form builder without actually creating <form> tags)

Fred

Hi I am also struck at the same point please help me ... same problem u r facing sandeep