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