Problems re-populating select options in Rails when form returned with errors
- by Rick
I have a form with 2 select options in it -- frequency and duration. When there are errors with the form, and it is returned to the browser, the select options are not re-populated with the selections the user made even though the returned values for those fields match the values of options in the selects. Also, when the form is returned, these fields are not marked as having errors even though their values are blank.
Here's the frequency and duration fields in Rails
<%= frequency_select c, :frequency %>
<%= duration_select c, :duration %>
The method for frequency_select is
def frequency_select(f, method)
options = [["day", 1.day], ["other day", 2.days], ["week", 1.week]]
f.select method, options, :include_blank => true
end
And the method for duration_select is
def duration_select(f, method, unit="day" )
values, units = *case unit
when "day" : [[[5, 5], [15, 15], [30, 29]], "days"]
when "other day" : [[[15, 15], [30, 29], [45,45]], "days"]
when "week" : [[[4, 29], [6, 43], [8, 57]], "weeks"]
end
f.select method, values.map {|(label, i)| ["#{label} #{units}", i.days]}, :include_blank => true
end
If you enter a value into one or both of these fields and submit the form without completing part of it (any part of it), the form is returned to the user (as would be expected), but the duration and frequency fields are not re-populated with the user's selection.
If I add this bit of code to the form
<p><%= @challenge.attributes.inspect %></p>
I see that this for duration and frequency when the form is returned to the browser:
"duration"=>3888000, "frequency"=>172800
These values match values on the options in the select fields.
Is there anything special in Rails that needs to be done so that the select fields are re-populated with the user's selections? Any thoughts on what the problem could be or what I should try next?
Help is greatly appreciated!
-Rick
PS If you look at some of the other questions, you'll notice I've asked about this in the past. At one point, I thought the form was returning values for frequency and duration in days rather than seconds, but that's not the case.
PPS Here's one other bit of information that might matter, but my tests indicate that it probably does not. (Though, I'm a bit of a newbie to this, so don't take my word for it.)
These two fields are chained together using the cascade jquery plugin.
The javascript is included on the page (not in a separate file) and some of the js is being created by Rails.
First, here are the scripts as they appear in the browser. The first is the script to generate the options for the duration select and the second is the script required by the Cascade plugin to trigger the field chaining.
<script type="text/javascript">
var list1 = [
{'When':'86400','Value':' ','Text':' '},
{'When':'172800','Value':' ','Text':' '},
{'When':'604800','Value':' ','Text':' '},
{'When':'86400','Value':'432000','Text':'5 days'},
{'When':'86400','Value':'1296000','Text':'15 days'},
{'When':'86400','Value':'2505600','Text':'30 days'},
{'When':'172800','Value':'1296000','Text':'15 days'},
{'When':'172800','Value':'2505600','Text':'30 days'},
{'When':'172800','Value':'3888000','Text':'45 days'},
{'When':'604800','Value':'2505600','Text':'4 weeks'},
{'When':'604800','Value':'3715200','Text':'6 weeks'},
{'When':'604800','Value':'4924800','Text':'8 weeks'}
];
function commonTemplate(item) {
return "<option value='" + item.Value + "'>" + item.Text + "</option>";
};
function commonMatch(selectedValue) {
return this.When == selectedValue;
};
</script>
<script type="text/javascript">
jQuery(document).ready(function(){
jQuery("#challenge_duration, #user_challenge_duration").cascade("#challenge_frequency, #user_challenge_frequency",{
list: list1,
template: commonTemplate,
match: commonMatch
})
});
</script>
And here's a bit of the the first script as it is in the erb file -- you see that some of the script is being generated by Rails
<%=
[ [1.day, [[5, 5], [15,15], [30, 29]], "days"],
[2.days, [[15, 15], [30, 29], [45, 45]], "days"],
[1.week, [[4, 29], [6, 43], [8, 57]], "weeks"]].map do |(frequency, durations, unit)|
durations.map do |(label, value)|
"{'When':'#{frequency}','Value':'#{value.days}','Text':'#{label} #{unit}'}"
end
end.join(",\n")
-%>
Now, the reason I don't think that it matters whether the duration is being generated with JS is
the problem still exists if I remove all the JS
the problem also affects the frequency field, whose options are not being generated by the JS