Rails 3 with Prototype Making Dynamic Drop Downs inside a form with database calls
I have been searching for a good way to create dynamic dropdowns that are part of a form. The dropdowns need to be populated with data from the database based on the previous dropdown. I have not found a good rails 3/prototype solution. I have seen some partial solutions with jQuery and using prototype legacy helpers. However, I read it is not a good idea to use the legacy helpers so I am trying to do it without them while still using prototype.
I understand this is a large question however, I assume this has already been done several times and if somebody has a good how to it would be much appreciated. If not my plan of attack is use onchange to trigger a javascript call to send a request to the server. Then update the partial, the next select box, with the apropriate options and then repeat.
Immediate Question: How do you generate a ajax page call using prototype? I need to send the result of the first drop down to my controller. The url would be car_infos/update_make/"year".
I have this select tag in my larger form that calls a javascript function.
<%= select_tag 'year', options_from_collection_for_select(@vehicle_years, "year", "year"), {:include_blank => true, :onchange => "submitYear(this.value)" }%>
Thanks for any help as I get started with Rails.
Update: I am generating a request to the server with this javascript:
function submitYear(year){
new Ajax.Request('/udpate_make/'+year, {method: 'get'});
}
However, it doesn't generate the correct url. If I put /car_infos/update_make it generates car_infos/car_infos/udpate_make/. If I take at the /car_infos part it just does /update_make and leaves off the car_infos. I get two or none. Still not sure how to generate the proper url of 'car_infos/update_make/year' I will implement the observe optio开发者_运维百科n as mentioned by @Jaryl but still having problems with the url generation. Here is my routes...
resources :car_infos
match 'car_infos/update_make/:year', :controller => 'car_infos', :action => 'update_make'
Update: with another part of the journey
To solve the duplicate part of the url I had to do the following:
function submitYear(year){
new Ajax.Request('update_make/'+year, {method: 'get'});
}
Notice the missing / from the previous example. Still don't know why when putting car_infos in there it duplicates it. but at least I am generating a valid Ajax request to the server now.
Since you are using Rails 3, where legacy helpers are deprecated. You should use something like jQuery UJS. What you do is take out the JS helper codes from your select tag like so:
<%= select_tag 'year', options_from_collection_for_select(@vehicle_years, "year", "year") %>
Then in your JS file (I'm using jQuery here), you add codes that performs the JS function:
$('#year').change(function(e) {
// some AJAX call here using $('#year').val()
});
To do this in Prototype (see docs for observing events), it will be something like this:
Event.observe('#year', 'change', function(event) {
// ...
});
This is what I ended up doing to create my dynamic drop downs with Protoype in case anybody else is going down this path. Please let me know if there is a better way:
Create Routes for appropriate controller, my controller is car_infos
match 'car_infos/update_make/:year', :controller => 'car_infos', :action => 'update_make'
match 'car_infos/update_model/:year/:make', :controller => 'car_infos', :action => 'update_model'
Inside form have first dropdown built and render a partial.
<div id="year_sel">
<%= f.label :car_year %>
<%= select_tag 'year', options_from_collection_for_select(@vehicle_years, "year", "year"), {:include_blank => true, :onchange => "submitYear(this.value)" }%>
</div>
<div id="make_select">
<%= render 'make_sel' %>
</div>
Build the link in javascript in your application.js file:
function submitYear(year){
new Ajax.Request('update_make/'+year, { method: 'get'});
}
Have your .js.rjs file that responds to the ajax request and renders the partial.
page.replace_html('make_select', render('make_sel'))
In your controller function make sure it responds to the .js format.
Hope this helps somebody else since it took me two days to find all.
精彩评论