See how to dynamically change a select menu based on another select menu using Javascript. In this episode everything is kept client side which leads to a more responsive user interface.
Wow, some very great tips on using Javascript in Rails. How about an episode on the efficient use of Javascript e.g. compression or caching of large libraries such as prototype?
Very cool, I'm making a site right now and I was using rjs, but got stuck at the how do I observe at load (my js skills are very poor). Now I get the onload update and faster updates :D However I am doing this on Rails 1.2.3, so there are a few differences. I had to name my view dynamic_states.rhtml, but I still put the :controller/:aciton.:format route, and it works just fine. I also had to get prototype 1.6.0 because I was getting a javascript error that there was no document.observe function. I also recommend getting the latest scriptaculous because without it I was getting a javascript recursion error on another part of my site. Now I just cross my fingers and hope that the new javascript libs and old Rails play nice together for the duration of the site being built :D
oops, I forgot to mention that I also had to put render :layout => false inside the dynamic_states controller so that I don't get all my html headers in what's supposed to be a javascript file
hey, u guys are doing a great job. i happened to come to ur site from www.techscreencast.com. They have a section full of videos on ror... some of the videos are from here... just wanted to say my thanks for ur efforts...
haha. I JUST implemented this a couple days ago (non-AJAX cascading selects). I'll have to revisit my code now that you've got this up. thanks for all the great screencasts
hey, i guess it would be easier (less js), more responsive (no dom-(re)generation), more accessible (optgroups do logic grouping), cleaner (no global vars in js) to just group the options and show or hide the group-of-options according to the selected country...
<select>
<optgroup label="..." id="x">
<option></option>
</optgroup>
here in brazil, for example, we always use something like this with States and Cities, and we have over 5000 cities and 27 states. for this case, isn´t ajax the best solution ?? could u show us how??
If anyone is interested, I have a plugin called applicability that does something like this automatically. Mine, however, is for turning parts of a form on or off based on a select menu.
Thanks for putting this up. Dynamic selects menus without buggy js plugins is exactly what I've been looking for. I'm having some trouble implementing though.
myhost/javascripts/dynamic_states.js renders normally. The script seems to load in the 'new' action given the html source of my view, though I noticed your helper method doesn't spit errors when given non-existent javascripts. The select id tags in dynamic_states line up with the ones in my the view. Still no action upon selecting country though. Any idea what I might be missing? I assume this works with remote_form_for?
Similar to Peter I'm having a few problems implementing this.
With implementation identical to yours navigating to
http://0.0.0.0:3000/javascripts/dynamic_show_requirements.js
renders:
"Missing template ....requirements.rhtml"
(nb. filename is "...requirements.js.erb")
Any quick tips as to how to get this moving?
Rails v 2.0.2 and Ruby v1.8.6
Scrap that - folks make sure you've got rails (including environment.rb) updated to latest and got your javascripts (as mentioned above updated to latest) using the command:
rake rails:update:javascripts
After having been working on something like this episode, rails seems unable to render my javascript and I need to update my routes and add the following line:
Ryan. I have followed the tutorial to the letter and i still can't get it to work. When i look at the javascript file /javascripts/dynamic/states.js i get the same as you do. However when i load a page the dynamicness just doesn't work... any ideas?
Hi Ryan,
thanks for your wonderful series. We had some trouble with your javascript. If there is only one state in a selected country, your script displayed that state twice. To fix that we changed "options.length = 1;" to "options.length = 0;" and also the if clause to "if(options.length == 0)"
Great tutorial. However, if a validation error occurs on one of the fields on the same page and the page is re-rendered with an error message the state drop down gets messed up. The prompt message is no longer there and the first state in the DB is there instead. Any ideas....?
How can it work with your 3-part complex forms casts?
When you add new task and each task on page will have those related dropdown how you refer to them?
When you add new task the div that you create in "simplify_views_for_rails_2.0" has id="new_task".
Each has id="new_task" and it is mark-up error.
Can you figure that out, cause that will be helpful!:)
ps. great railscasts! continue!
Ok I've solved it.
You got to modify your js.erb file, so it won't observe since you can't get the elements with the same ID from the js file.
So in partial with countries and states do:
f.collection_select(:country, Country.find(:all), :id, :name, {:include_blank => true }, :onchange => "collectionSelected(this);")
And your js.erb will look like:
// array generation
function collectionSelected(e) {
country_id = e.getValue();
options = e.next(1).options;
options.length = 1;
states.each(function(model) {
if (state[0] == country_id) {
options[options.length] = new Option(state[1], state[2]);
}
});
}
I would love to see this same problem solved using Ajax. I am doing the exact same thing you show here (country -> states), however, I've put together a couple of lookup tables (using the United Nations website) that has every country, and all the "states" for each and every country.
This "state" list contains about 3500 records and I just don't think that I want to use javascript for that every single time.
So, I humbly ask if you would do the same Railscast to show the Ajax method as an alternative.
Thanks first.
I've managed to make this work, but had two problems.
First, a non-related state option will display for every country, this is solved by modifying the first options.length = 1; to options.length = 0;
The other problem: On edit page, which also is using these codes, I find the saved state information is lost. The selector's default value fixs to the first option available for the country. I have no idea to fix this.
FireBug reports:
document.observe is not a function
[Break on this error] document.observe('dom:loaded', function() {
check you have included <%= javascript_include_tag 'prototype' %> in your layout used in the edit page otherwise you need to check your $('person_country_id').observe('change', countrySelected); and ensure that person_country_id is the correct id in your edit view.
Thanks for the great podcast. I am still very new at programming in Rails, so please forgive this comment if it's already obvious to everyone else.
I was using Prototype Javascript 1.5.0 as part of RailsI so I too was getting the "document.observe is not a function" error message. I decided to upgrade to "RailsII" which includes Prototype 1.6.0.
But the error persisted, until I noticed that the "public/javascripts" folder in my application code tree that I had copied over from RailsI included the older versions of the Prototype library.
Just copying the newer Prototype library into the "public/javascripts" folder seemed to do the trick.
Hope this is helpful.
Internet Explorer needs var added to new variables to avoid the 'Object or method not found'
// javascripts/dynamic_states.js.erb
var states = new Array();
<% for state in @states -%>
states.push(new Array(<%= state.country_id %>, '<%=h state.name %>', <%= state.id %>));
<% end -%>
function countrySelected() {
var country_id = $('person_country_id').getValue();
var options = $('person_state_id').options;
options.length = 1;
states.each(function(state) {
if (state[0] == country_id) {
options[options.length] = new Option(state[1], state[2]);
}
});
if (options.length == 1) {
$('state_field').hide();
} else {
$('state_field').show();
}
}
Is it me, or is there a lot of stuff missing if you don't follow these tutorials in order?
I tried following along with this one (Dynamic Select Menus) and all of a sudden kept running into things that were not mentioned in the video: for example, creating the "new" action, creating the Countries and States tables in the db, modifying the routes.rb file (OK, that one was mentioned, just late in the video), etc.
It's impossible to follow along when you don't have the groundwork covered, and now I don't know where the info is that I missed.
I have give you approach a try and it works pretty fine.
One thing though is that this way you end up with a two round call to rails to fulfill the request, one call to the people_controller and another to the javascripts_controller, with the repeating of bussiness processing if the thing get too complex.
If you want to try another approach this one looks fine:
http://railsenvy.com/2008/1/3/unobtrusive-javascript
oops sorry (I've made a two round posting here :-> )
@martin:
las rutas por defecto de rails funcionan, fijate si no las has eliminado en alguna refactorizacion REST, sino hay otro screencast sobre custom_routes en REST
sorry about posting in spanish, but:
en este
<a href="http://qvitta.net/articles/2008/04/24/javascript-no-obstrusivo-o-cuando-ajax-es-un-problema">post comento un poco los problemas de ajax, este enfoque y demas</a> en español! si os lo quereis mirar.
What if I want to record the country name and state name in the person model (rather than their id?) But I still want to record country_id in the state model. Can anyone point me in the right direction?
I love these tips! It would be very nice if you could package the files for examination. I'm having trouble understanding were your view code includes the state field.
I made some progress and discovered that my problem is trying to use this technique with a DIV that gets updated with RJS. I can't seem to get the javascript to be interpreted unless I put it on the main page, but then the observed fields are not available.
Any ideas on how to use this technique for partials that come and go with RJS/Ajax?
Is it possible to use this same concept to build a list to use with Drag and Drop? I'd like to load the lists and display only those states related to the country, but instead of a select list, the user is dragging and dropping values to create a list of items.
If so, any ideas on how to modify the function countrySelected to create my list elements?
I am using the Rails 1.2.3, and follow the instruction that clouder said. But it looks like I still miss the dynamic_states.js, even I have correct output in http://localhost:3000/javascripts/dynamic_states. Could someone give any suggestion? Thanks!
I have tried everything in the tutorial and the comments including May 22 08 comment by "pi_p master" for respond_to do format etc. and here is my predicament; my application works on my development machine just fine; when I transport it to my production environment it does not call the javascripts controller; I have the following error : <script type="text/javascript" src="/javascripts/dynamic_units.js">
1<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
2<html><head>
3<title>404 Not Found</title>
4</head><body>
5<h1>Not Found</h1>
6<p>The requested URL /javascripts/dynamic_units.js was not found on this server.</p>
7</body></html>
Now I have even tried putting in explicitly map.connect ':controller/:action.:format'
I am having the same exact problem as Captain Zhan. This script totally borks out on the edit action. It forgets the state I selected even though I see it clearly saved in the database.
All of my javascripts are definitely included and the script still works - if I change the country, the state list changes, but the initial load is screwed up and automatically selects the first state in the list, instead of the state saved in the DB.
As a temporary solution, I simply do not load the script i current action is edit, but thats not too cool of a fix.
For those of you pulling your hair out with this complicated solution, there is an excellent pluin that handles all this fun stuff in just a few lines of helper code.
"Check it out!":http://dvisionfactory.googlecode.com/svn/rails/plugins/related_select_forms/
Hi, I'm trying to get this up and running in a scenario in which a person has a state and a state has a country, but a person doesn't have a country except through the state. In this case, the collection_select for country won't work. I'm trying to use a combined call to select_tag and options_from_collection_select to give me just the tags, but I haven't been able to get it to work yet.
I've also taken pimpmaster's suggestion about formatting, and should also mention that as with Vysogot, I'm trying to do this with something structurally similar to the projects/tasks application which is explored in the three part complex forms series. I haven't gotten too deep into trying Vysogot's solution for this to see if that get's things working, but I figured I would see if anyone could could me a quick suggestion on approach - I'll post more when I figure out more.
I was able to successfully implement this with the 3-part complex forms application. Vysogot's solution worked, but I had to make a couple of further modifications. Here is the code from my _task partial
<label for="task_state_id">State or Province:</label>
<%= task_form.collection_select :state_id, State.find(:all), :id, :name, :prompt => "Select a State" %>
</p>
...
Here's what I changed:
-I had to call :country_id (not :country) in the collection_select
-I put the collection_selects in the the same <p> element so that the call to .next() works properly.
-I put the :onchange call in {} brackets
-'model' in the def of collectionSelected() should have been 'state'
I think that that's it for the complex forms application. I'm still not sure how to get this to work with my application, since as I mentioned I can't use collection_select, as what will effectively be the person in my application has a state, but a country only through a state. I'll keep working on it, but if anyone knows what to use instead of a collection_select I would appreciate a comment on it.
Oh, and thanks to Ryan and everyone else who helps everyone out here - Awesome!
Alright, so I got it to work using options_from_from_collection_for_select to get the options and then feeding them into a select_tag method. It works, but a) it seems like there is a prettier way to do it and b) I'm not sure how to specify a prompt. I've tried putting :prompt => "Select a such and Such" both at the end of the select_tag call and the options_ from_col.. call, and neither works. If anyone has solutions to these minor queries, answers would be welcome and appreciated.
I'm having some trouble with the edit using this method.
For example:
When I go to the edit, and i have several countries associated to it's continents, it keeps the value selected (for example China for the Asian continent). When I change the continent in the parent select it replaces all the select but not the prompted edit value (in this case China).
The question is, how can I replace that first value in the edit view?
I am using the Rails 1.2.3, and follow the instruction that clouder said. But it looks like I still miss the dynamic_states.js, even I have correct output in http://localhost:3000/javascripts/dynamic_states. Could someone give any suggestion? Thanks!
It's probably better to use double quotes around the state name in the js file since a state name might contain a single quote. Ex. "Provence-Alpes-Cote d'Azur"
In dynamic_states.js change '<%=h state.name %>' to "<%=h state.name %>"
The suggested code doesn't select the state from the drop-down if it's already selected for me. Not sure what I'm doing differently from the suggested code.
Adding an if statement and a few parameters to the 'new Option(name, id, false, true)' are what worked: http://gist.github.com/45324
hey! first comment comes from germany. great episode, ryan! every monday 9:00 in the morning, it's time to watch railscasts! philipp
The <code>content_for(:head)</code> is very sweet!
I was just going to figure out how to do this today! Thanks for saving me time and effort once again!!
Wow, some very great tips on using Javascript in Rails. How about an episode on the efficient use of Javascript e.g. compression or caching of large libraries such as prototype?
Thanks!
Chris
Railscast is like Knoppers, every morning at 9:30 in Poland :)
Very cool, I'm making a site right now and I was using rjs, but got stuck at the how do I observe at load (my js skills are very poor). Now I get the onload update and faster updates :D However I am doing this on Rails 1.2.3, so there are a few differences. I had to name my view dynamic_states.rhtml, but I still put the :controller/:aciton.:format route, and it works just fine. I also had to get prototype 1.6.0 because I was getting a javascript error that there was no document.observe function. I also recommend getting the latest scriptaculous because without it I was getting a javascript recursion error on another part of my site. Now I just cross my fingers and hope that the new javascript libs and old Rails play nice together for the duration of the site being built :D
oops, I forgot to mention that I also had to put render :layout => false inside the dynamic_states controller so that I don't get all my html headers in what's supposed to be a javascript file
hey, u guys are doing a great job. i happened to come to ur site from www.techscreencast.com. They have a section full of videos on ror... some of the videos are from here... just wanted to say my thanks for ur efforts...
haha. I JUST implemented this a couple days ago (non-AJAX cascading selects). I'll have to revisit my code now that you've got this up. thanks for all the great screencasts
Ryan - thanks a lot for doing this episode. It's been hard to find a solid tutorial on dynamic select menus.
Why can't I see the video on my iphone? I only hear the audio. I'm subscribed to the ipod version.
Anyhow, keep up the good work, nice podcasts! I wish I could watch them at the gym, though ;-)
hey, i guess it would be easier (less js), more responsive (no dom-(re)generation), more accessible (optgroups do logic grouping), cleaner (no global vars in js) to just group the options and show or hide the group-of-options according to the selected country...
<select>
<optgroup label="..." id="x">
<option></option>
</optgroup>
<optgroup label="..." id="y">
<option></option>
</optgroup>
<optgroup label="..." id="z">
<option></option>
</optgroup>
</select>
... but as always... thank you for your efforts
great job/idea!!
here in brazil, for example, we always use something like this with States and Cities, and we have over 5000 cities and 27 states. for this case, isn´t ajax the best solution ?? could u show us how??
congratulations for this screencast!!
If anyone is interested, I have a plugin called applicability that does something like this automatically. Mine, however, is for turning parts of a form on or off based on a select menu.
http://code.google.com/p/applicability/
Jon
Thank you Ryan, that's one more neat screencast which came exactly when I needed it most.
Unfortunately there is at least one major issue:
What if you want to edit the stuff later? The child item won't be select, you have to choose again :(
Thanks for putting this up. Dynamic selects menus without buggy js plugins is exactly what I've been looking for. I'm having some trouble implementing though.
myhost/javascripts/dynamic_states.js renders normally. The script seems to load in the 'new' action given the html source of my view, though I noticed your helper method doesn't spit errors when given non-existent javascripts. The select id tags in dynamic_states line up with the ones in my the view. Still no action upon selecting country though. Any idea what I might be missing? I assume this works with remote_form_for?
Similar to Peter I'm having a few problems implementing this.
With implementation identical to yours navigating to
http://0.0.0.0:3000/javascripts/dynamic_show_requirements.js
renders:
"Missing template ....requirements.rhtml"
(nb. filename is "...requirements.js.erb")
Any quick tips as to how to get this moving?
Rails v 2.0.2 and Ruby v1.8.6
Thanks for the podcast! :)
Scrap that - folks make sure you've got rails (including environment.rb) updated to latest and got your javascripts (as mentioned above updated to latest) using the command:
rake rails:update:javascripts
Thanks Ryan!
Taking out "countrySelected();" in the amended javascript makes this work for my app on rails 2.0.2.
I would like to filter the states list by the pre-selected country though. What might I be missing?
After having been working on something like this episode, rails seems unable to render my javascript and I need to update my routes and add the following line:
<code> map.connect ':controller/:action.:format'</code>
Great article though...
Sorry, it's not a great article but a great rails screencast. :)
Just as a note, all javascripts should be included at the bottom of the page right before the body close tag. It's better performance wise.
Thanks for this episode
What's the use of "*files" in the helper method, looks like some kind of dereferenced pointer to me - I'm certainly not a ruby guru ;-)
Ryan. I have followed the tutorial to the letter and i still can't get it to work. When i look at the javascript file /javascripts/dynamic/states.js i get the same as you do. However when i load a page the dynamicness just doesn't work... any ideas?
Hi Ryan,
thanks for your wonderful series. We had some trouble with your javascript. If there is only one state in a selected country, your script displayed that state twice. To fix that we changed "options.length = 1;" to "options.length = 0;" and also the if clause to "if(options.length == 0)"
Hello Ryan,
great tutorial, exactly what I was looking for.
Thanks for this and all your terrific podcasts
Is it possible to implement the same logic using 3 dynamic menus?
Hey Ryan,
Great tutorial. However, if a validation error occurs on one of the fields on the same page and the page is re-rendered with an error message the state drop down gets messed up. The prompt message is no longer there and the first state in the DB is there instead. Any ideas....?
How can it work with your 3-part complex forms casts?
When you add new task and each task on page will have those related dropdown how you refer to them?
When you add new task the div that you create in "simplify_views_for_rails_2.0" has id="new_task".
Each has id="new_task" and it is mark-up error.
Can you figure that out, cause that will be helpful!:)
ps. great railscasts! continue!
Ok I've solved it.
You got to modify your js.erb file, so it won't observe since you can't get the elements with the same ID from the js file.
So in partial with countries and states do:
f.collection_select(:country, Country.find(:all), :id, :name, {:include_blank => true }, :onchange => "collectionSelected(this);")
And your js.erb will look like:
// array generation
function collectionSelected(e) {
country_id = e.getValue();
options = e.next(1).options;
options.length = 1;
states.each(function(model) {
if (state[0] == country_id) {
options[options.length] = new Option(state[1], state[2]);
}
});
}
and thats it :)
Interesting, as usual.
I would love to see this same problem solved using Ajax. I am doing the exact same thing you show here (country -> states), however, I've put together a couple of lookup tables (using the United Nations website) that has every country, and all the "states" for each and every country.
This "state" list contains about 3500 records and I just don't think that I want to use javascript for that every single time.
So, I humbly ask if you would do the same Railscast to show the Ajax method as an alternative.
Thanks!
B.
Thanks first.
I've managed to make this work, but had two problems.
First, a non-related state option will display for every country, this is solved by modifying the first options.length = 1; to options.length = 0;
The other problem: On edit page, which also is using these codes, I find the saved state information is lost. The selector's default value fixs to the first option available for the country. I have no idea to fix this.
FireBug reports:
document.observe is not a function
[Break on this error] document.observe('dom:loaded', function() {
@Captain Zhan
check you have included <%= javascript_include_tag 'prototype' %> in your layout used in the edit page otherwise you need to check your $('person_country_id').observe('change', countrySelected); and ensure that person_country_id is the correct id in your edit view.
Thanks for the great podcast. I am still very new at programming in Rails, so please forgive this comment if it's already obvious to everyone else.
I was using Prototype Javascript 1.5.0 as part of RailsI so I too was getting the "document.observe is not a function" error message. I decided to upgrade to "RailsII" which includes Prototype 1.6.0.
But the error persisted, until I noticed that the "public/javascripts" folder in my application code tree that I had copied over from RailsI included the older versions of the Prototype library.
Just copying the newer Prototype library into the "public/javascripts" folder seemed to do the trick.
Hope this is helpful.
Internet Explorer needs var added to new variables to avoid the 'Object or method not found'
// javascripts/dynamic_states.js.erb
var states = new Array();
<% for state in @states -%>
states.push(new Array(<%= state.country_id %>, '<%=h state.name %>', <%= state.id %>));
<% end -%>
function countrySelected() {
var country_id = $('person_country_id').getValue();
var options = $('person_state_id').options;
options.length = 1;
states.each(function(state) {
if (state[0] == country_id) {
options[options.length] = new Option(state[1], state[2]);
}
});
if (options.length == 1) {
$('state_field').hide();
} else {
$('state_field').show();
}
}
document.observe('dom:loaded', function() {
countrySelected();
$('person_country_id').observe('change', countrySelected);
});
Is it me, or is there a lot of stuff missing if you don't follow these tutorials in order?
I tried following along with this one (Dynamic Select Menus) and all of a sudden kept running into things that were not mentioned in the video: for example, creating the "new" action, creating the Countries and States tables in the db, modifying the routes.rb file (OK, that one was mentioned, just late in the video), etc.
It's impossible to follow along when you don't have the groundwork covered, and now I don't know where the info is that I missed.
por favor me dicen cuales serian las rutas routes.rb
me genera el siguiente error:
ActionController::RoutingError (No route matches "/javascripts/dynamic_states.js" with {:method=>:get}):
A mi tambien me sucede lo mismo, lo que sucede al parecer es que en el recorrido del video Ryan Bates olvido modificar las rutas.
Hey guys this is the solution, match "javascripts/dynamic_states" => "javascripts#dynamic_states"
gracias. es posible ajustarlos para dos combobox mas?
saludos
hi,
great work.
I have give you approach a try and it works pretty fine.
One thing though is that this way you end up with a two round call to rails to fulfill the request, one call to the people_controller and another to the javascripts_controller, with the repeating of bussiness processing if the thing get too complex.
If you want to try another approach this one looks fine:
http://railsenvy.com/2008/1/3/unobtrusive-javascript
keep on the good work
oops sorry (I've made a two round posting here :-> )
@martin:
las rutas por defecto de rails funcionan, fijate si no las has eliminado en alguna refactorizacion REST, sino hay otro screencast sobre custom_routes en REST
that's it
sorry about posting in spanish, but:
en este
<a href="http://qvitta.net/articles/2008/04/24/javascript-no-obstrusivo-o-cuando-ajax-es-un-problema">post comento un poco los problemas de ajax, este enfoque y demas</a> en español! si os lo quereis mirar.
Great stuff Ryan!
I have a question though (for anyone).
What if I want to record the country name and state name in the person model (rather than their id?) But I still want to record country_id in the state model. Can anyone point me in the right direction?
I love these tips! It would be very nice if you could package the files for examination. I'm having trouble understanding were your view code includes the state field.
I made some progress and discovered that my problem is trying to use this technique with a DIV that gets updated with RJS. I can't seem to get the javascript to be interpreted unless I put it on the main page, but then the observed fields are not available.
Any ideas on how to use this technique for partials that come and go with RJS/Ajax?
Is it possible to use this same concept to build a list to use with Drag and Drop? I'd like to load the lists and display only those states related to the country, but instead of a select list, the user is dragging and dropping values to create a list of items.
If so, any ideas on how to modify the function countrySelected to create my list elements?
THANKS!
I am using the Rails 1.2.3, and follow the instruction that clouder said. But it looks like I still miss the dynamic_states.js, even I have correct output in http://localhost:3000/javascripts/dynamic_states. Could someone give any suggestion? Thanks!
FYI: I had problems in Rails 2.0.2 until I added this line to that dynamic states action
respond_to do |format|
format.js
end
I also had to add this to routes.rb:
map.js ':controller/:action.:format'
And now everything works
Hope it helps someone :)
Extremely useful, thanks! This just saved me a couple of hours of searching the net. Thanks, Ryan!
I have tried everything in the tutorial and the comments including May 22 08 comment by "pi_p master" for respond_to do format etc. and here is my predicament; my application works on my development machine just fine; when I transport it to my production environment it does not call the javascripts controller; I have the following error : <script type="text/javascript" src="/javascripts/dynamic_units.js">
1<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
2<html><head>
3<title>404 Not Found</title>
4</head><body>
5<h1>Not Found</h1>
6<p>The requested URL /javascripts/dynamic_units.js was not found on this server.</p>
7</body></html>
Now I have even tried putting in explicitly map.connect ':controller/:action.:format'
as well as :
map.js '/javascripts/dynamic_units.js' , :controller=>'javascripts', :action =>'dynamic_units'
and whatever permutation I could fathom but to no avail. Help please.
I am having the same exact problem as Captain Zhan. This script totally borks out on the edit action. It forgets the state I selected even though I see it clearly saved in the database.
All of my javascripts are definitely included and the script still works - if I change the country, the state list changes, but the initial load is screwed up and automatically selects the first state in the list, instead of the state saved in the DB.
As a temporary solution, I simply do not load the script i current action is edit, but thats not too cool of a fix.
Anyone else deal with this?
Where is Ryan???? *shines Bat Signal*
For those of you pulling your hair out with this complicated solution, there is an excellent pluin that handles all this fun stuff in just a few lines of helper code.
"Check it out!":http://dvisionfactory.googlecode.com/svn/rails/plugins/related_select_forms/
It also works well on edit!
Tanks for this screencast!
@Harry J The plugin you mentioned works great!
Having said that, I also think the screencast is excellent, because it is all about learning and seeing new or 'unknown' techniques.
Hola tengo un problema con este tutorial. Hice exactamente cada paso pero aplicado a mi proyecto y me sale el siguiente error.
You have a nil object when you didn't expect it!
You might have expected an instance of Array.
The error occurred while evaluating nil.each
Extracted source (around line #2):
1: var versions = new Array();
2: <% for producto in @productos -%>
3: versions.push(new Array(<%= version.producto_id %>, '<%=h version.verprod %>', <%= version.id %>));
4: <% end -%>
5:
hey guys,
I am trying to do this with a has_many :through relationship.
job, division, job_division
i am unsure whether to use the job_division 'join' table as the model in the js.erb file
Any ideas?
Hi, I'm trying to get this up and running in a scenario in which a person has a state and a state has a country, but a person doesn't have a country except through the state. In this case, the collection_select for country won't work. I'm trying to use a combined call to select_tag and options_from_collection_select to give me just the tags, but I haven't been able to get it to work yet.
I've also taken pimpmaster's suggestion about formatting, and should also mention that as with Vysogot, I'm trying to do this with something structurally similar to the projects/tasks application which is explored in the three part complex forms series. I haven't gotten too deep into trying Vysogot's solution for this to see if that get's things working, but I figured I would see if anyone could could me a quick suggestion on approach - I'll post more when I figure out more.
Cheers
In relation to the edit form not remembering the child. I got around it by added another onload observer to set the value.
<script>
document.observe('dom:loaded', function() {
$('person_state_id').value = <%= @person.state_id %>;
});
</script>
Not the most elegant, but it works! Good Luck!
I was able to successfully implement this with the 3-part complex forms application. Vysogot's solution worked, but I had to make a couple of further modifications. Here is the code from my _task partial
...
<label for="task_country_id">Country:</label>
<%= task_form.collection_select :country_id, Country.find(:all), :id, :name, {:prompt => "Select a Country"}, {:onchange => "collectionSelected(this);"} %>
<label for="task_state_id">State or Province:</label>
<%= task_form.collection_select :state_id, State.find(:all), :id, :name, :prompt => "Select a State" %>
</p>
...
Here's what I changed:
-I had to call :country_id (not :country) in the collection_select
-I put the collection_selects in the the same <p> element so that the call to .next() works properly.
-I put the :onchange call in {} brackets
-'model' in the def of collectionSelected() should have been 'state'
I think that that's it for the complex forms application. I'm still not sure how to get this to work with my application, since as I mentioned I can't use collection_select, as what will effectively be the person in my application has a state, but a country only through a state. I'll keep working on it, but if anyone knows what to use instead of a collection_select I would appreciate a comment on it.
Oh, and thanks to Ryan and everyone else who helps everyone out here - Awesome!
Alright, so I got it to work using options_from_from_collection_for_select to get the options and then feeding them into a select_tag method. It works, but a) it seems like there is a prettier way to do it and b) I'm not sure how to specify a prompt. I've tried putting :prompt => "Select a such and Such" both at the end of the select_tag call and the options_ from_col.. call, and neither works. If anyone has solutions to these minor queries, answers would be welcome and appreciated.
Thanks again!
I'm having some trouble with the edit using this method.
For example:
When I go to the edit, and i have several countries associated to it's continents, it keeps the value selected (for example China for the Asian continent). When I change the continent in the parent select it replaces all the select but not the prompted edit value (in this case China).
The question is, how can I replace that first value in the edit view?
nice screencast! thanks!
Just as a note, all javascripts should be included at the bottom of the page right before the body close tag. It's better performance wise.
I am using the Rails 1.2.3, and follow the instruction that clouder said. But it looks like I still miss the dynamic_states.js, even I have correct output in http://localhost:3000/javascripts/dynamic_states. Could someone give any suggestion? Thanks!
@Werbeagentur,
Try http://localhost:3000/javascripts/dynamic_states.js
@Werbeagentur,
Sorry! I misunderstood your question! I had the same problem actually. What does your HTML look like for your "states" in your form?
Great work there..
I get this error. I'm using rails 2.1
No route matches "/javascripts/dynamics_states.js" with {:method=>:get}
[@Matt, @Herbalife] It does work with 2.1. There's a route you have to set - see http://gist.github.com/12391
Sorry! I misunderstood your question! I had the same problem actually. What does your HTML look like for your "states" in your form?
@ Johny: many thanks!
Very complicated but I´ll try it!
Thank you.
Not to easy. But if you read carefully it works
Very interesting write up. But its difficult to understand!
thanks for the awesome script.. i'm just wondering which one is better compare to using ajax..
Seems a little complicated first, but when reading it carefully, it works...
This episode was great! Thanks.
ingilizce tercüme
Very interesting write up.
Good very good!!
Great tutorial but not easy to understand. Thanks a lot for our help.
This broke for me when upgrading to 2.2.2
The content_for capture in application_helper.rb doesn't fail, but it also doesn't insert the stylesheet/javascript into the template.
Any ideas?
This description really helped me a lot. Thanks. ;)
Thanks Ryan,I think this is one of the most wonderful sites. I have great admiration for you.Gayrimenkul degerleme ekspertiz
This broke for me when upgrading to 4 5 kiralık satılık emlak gayrimenkul
You really helped me out with this. Thank you very much!
I searched for dynamic menus in Ruby and your article helps me a lot... Thanks for posting it. Great help!
can this be used in os commerce?
I should try those codes, thanks
Great job and good idea !
Congratulations for this screencast !! Best Regards Holz-Export
The first time I tried this I was using Rails 1.2.3 so I skipped the js.erb file and implemented the javascript directly in the html page.
Now I'm working on another project using Rails 2.2.2 and was able to implement the way you show. It works great.
Thanks to Peer Allan for sharing how he fixed the edit form issue.
Any ideas why I'm getting "Missing layout layouts/application.erb in view path /myapp/app/views"?
For some reason when rendering the .js template my app is trying to use the wrong (non-existant) layout mentioned above.
It's probably better to use double quotes around the state name in the js file since a state name might contain a single quote. Ex. "Provence-Alpes-Cote d'Azur"
In dynamic_states.js change '<%=h state.name %>' to "<%=h state.name %>"
Any Idea how to include javascript file from a partial loaded via rjs ?
Thanks !
To answer my question post 131, couldn't find a way to execute javascript_include_tag in a partial loaded through .rjs.
I used javascript_tag straight in the view to refresh js global variable.
The suggested code doesn't select the state from the drop-down if it's already selected for me. Not sure what I'm doing differently from the suggested code.
Adding an if statement and a few parameters to the 'new Option(name, id, false, true)' are what worked: http://gist.github.com/45324
I aggree. Amazing and helpful. Love Rails ;)