SitePoint Sponsor |
|
User Tag List
Results 1 to 16 of 16
Thread: Drop Down Menu
-
Jun 22, 2009, 12:29 #1
- Join Date
- Jun 2009
- Posts
- 53
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
Drop Down Menu
Hey guys -
I'm trying to use a drop-down menu to allow a user select a value for submission along with some text-input fields. I have a submit_tag handling the submission.
I can't figure out what's wrong with this syntax:
Code:<td width = 275px, align = "center"> <select name= "status" > <option value="option1">Option 1</option> <option value="option2">Option 2</option> <option value="option3">Option 3</option> </select> </td>
I have "validates_presence_of :status" in my project model, which seems to be doing its job because the page just refreshes when I submit. Without the validation, it claims status is nil.
Thanks for your time!
-
Jun 22, 2009, 15:51 #2
- Join Date
- Feb 2006
- Location
- Worcs. UK
- Posts
- 404
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
The important bit that you appear to be missing is the controller code. You need to catch the value returned by the page in the controller code via params and then pass it to an instance of the model. So this would work:
Code:def edit thing = Thing.new thing.status = params[:status] thing.save end
Controller
Code:def edit @status_options = ['option_1', 'option_2', option_3'] thing = Thing.new if request.post? and params[:thing] thing.attributes = params[:thing] thing.save end end
Code:<%= error_messages_for(:thing) %> <% form_tag do %> <%= select (:thing, :status, @status_options.collect{|o| [o.humanize, o]}) %> <%= commit_tag %> <% end %>
By default, rails methods return items from forms in the format:
Code:params[:object_name][:method_name]
Code:if request.post? and params[:thing] thing.status = params[:thing][:status] thing.save end
-
Jun 22, 2009, 19:33 #3
- Join Date
- Jun 2009
- Posts
- 53
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
Thanks for the generosity. I'm having a little trouble with the "humanize" bit...any brief explanation of the iteration would be appreciated.
I actually have a global array "@status_values" in my application controller. I was trying to use this as the "choices" attribute for the select function, but I couldn't get it to work.
Thank you again for your time
-
Jun 23, 2009, 05:58 #4
- Join Date
- Feb 2006
- Location
- Worcs. UK
- Posts
- 404
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
Code:<%= select (:thing, :status, @status_options.collect{|o| [o.humanize, o]}) %>
Code:[ ["Label 1", "label_1"], ["Label 2", "label_2"], ["Label 3", "label_3"] ]
Select will convert that array of arrays into:
Code:<option value="label_1">Label 1</option> <option value="label_2">Label 2</option> <option value="label_3">Label 3</option>
Code:test_array = ['an_entry'] result_array_1 = test_array.collect{|e| [e, e]} result_array_2 = test_array.collect{|e| [e.humanize, e]}
Code:result_array_1 ----> [ ["an_entry", "an_entry"] ] result_array_2 ----> [ ["An entry", "an_entry"] ]
-
Jun 23, 2009, 06:46 #5
- Join Date
- Jun 2009
- Posts
- 53
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
:hug:
Thank you VERY much. hopefully this helps some future form-doers.
I did make a slight change; I defined the array of sub arrays explicitly in my application controller and I didn't use "commit_tag" - ruby didn't recognize it. It's working though:
Code:<% form_tag do %> <%= select (:project, :status, @status_options) %> <% end %>
.
-
Jun 23, 2009, 09:33 #6
- Join Date
- Jun 2009
- Posts
- 53
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
Here's another related question - thank you for looking.
My objective is to have a select menu with submittable options (currently working) that dynamically generates another select menu according to what's been selected. I won't need to access anything from a database.
The mother select-menu would have Status 1, Status 2, and Status 3.
The child select-menu would have Level 1, Level 2, Level 3. The values of Level change according to each Option. Eg Option 1's Level 1 would be 20, wheras Option 2's Level 1 would be 40.
I think it would be something like this:
Code:<% form_tag do %> <%= select (:project, :status, @status_options, {onchange => ( select (:project, :level, @%status%_options}) %> <% end %>
How exactly would I get the %status% working?
-
Jun 23, 2009, 11:57 #7
- Join Date
- Jun 2009
- Posts
- 53
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
Just posting my progress...
I decided to generate each Option's form in separate <div>s, and have them hidden until the actual Option is selected. The <div> is then supposed to appear. I currently have each div set to
Code:style = "display:none"
I'll post up my solution if I figure it out.
-
Jun 23, 2009, 13:30 #8
- Join Date
- Jun 2009
- Posts
- 53
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
I feel like I'm so close! Not quite working..
Code:<% form_tag do %> <%= select (:project, :status, @status_options, {:include_blank => nil},{:onchange => "i=this.options[this.selectedIndex].text; if(i=='option1'){ show('option1'); hide('option2'); hide('option3');};"}) %> <% end %>
Code:function hide(s) { s.style.display = "none"; } function show(s) { s.style.display = "block"; } </script>
-
Jun 24, 2009, 07:39 #9
- Join Date
- Jun 2009
- Posts
- 53
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
I currently have the interface working, but not the submission.
Code:<% form_tag do %> <%= select (:project, :status, @status_options, {:include_blank => nil},{:onchange => " if(this.value.match(/option1/i)){ $('option1').show(); } else { $('option1').hide(); } if(this.value.match(/option2/i)){ $('option2').show(); } else { $('option2').hide(); } "})%>
Code:<div id = "option1" style = "display: none"> <% form_tag do %> <%= select (:project, :probability, @status_option1) %> <% end %> </div> <div id = "option2" style = "display: none"> <% form_tag do %> <%= select (:project, :probability, @status_option2) %> <% end %> </div>
Code:@status_option1 = [["Probability",nil],["High (70%)",0.7],["Medium (50%)",0.5],["Low (30%)",0.3]] @status_option2 = [["Probability",nil],["High (50%)",0.5],["Medium (20%)",0.2],["Low (10%)",0.1]]
-
Jun 24, 2009, 08:16 #10
- Join Date
- Jun 2009
- Posts
- 53
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
After looking at the generated HTML, I now know it's because the "probability" is being passed as a string, as opposed to integer. Trying to figure out how to get it passed as an int...
-
Jun 24, 2009, 11:45 #11
- Join Date
- Jun 2009
- Posts
- 53
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
So - now I have each div split up into a separate partial, and I'm trying to call the partial like this:
Code:<%= select (:project, :status, @status_options, {:include_blank => nil},{:onchange => render :partial => ("this.value" + "probs")})%>
-
Jun 24, 2009, 13:08 #12
- Join Date
- Feb 2006
- Location
- Worcs. UK
- Posts
- 404
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
Sorry. stupidity on my part. The method is "submit_tag"
http://api.rubyonrails.org/classes/A...r.html#M002024
-
Jun 24, 2009, 13:22 #13
- Join Date
- Feb 2006
- Location
- Worcs. UK
- Posts
- 404
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
I think you are trying to run before you can walk, and I'd suggest you start with a simpler design.
However, if you really want to get the sort of behaviour you describe, you need to use browser side functionality and that means JavaScript. You can use AJAX to simplify the coding, and you can also use Rails AJAX helpers to generate the AJAX code.
The reason your first version works and the second doesn't is because the former onchange calls a bit of JavaScript, and the latter calls a bit of Rails code. The onchange triggers an event client side - that is in the browser - and therefore the code that is executed has to be understood by the browser. Browsers don't understand Rails. You have to use Rails methods that generate the JavaScript/AJAX that will be run via the onchange trigger. Otherwise you can code the JavaScript/AJAX yourself.
I think my best advice would be to suggest that you invest in the excellent "Ajax on Rails" book by Scott Raymond. This is by far the best reference I've read on using AJAX in the Rails environment.
-
Jun 24, 2009, 13:45 #14
- Join Date
- Jun 2009
- Posts
- 53
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
Thanks for the reference Reggie. I'll read up on Ajax and have at it.
-
Jun 25, 2009, 11:54 #15
- Join Date
- Jun 2009
- Posts
- 53
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
I've skimmed through Scott's book, and it's definitely something I'll be studying. I also have "Agile Web Development with Rails" (3rd edition, Rails 2.0). Great examples in both. I wish Ajax on Rails had a bit more on select menus though...
After wrapping my head around some of the more general concepts, I went at this again with a different approach. I'm not sure if it's a "good" solution per se, but it's sort of working.
I went entirely with javascript to contol the actions within a div. This div contains the "optional" sub-menu that may or may not be displayed.
Code:<select onchange= "getprob(this.value)"
Code:function getprob(id){ switch (id){ case "lead": show("probability_select"); document.projectform.project_probability.options[0] = new Option("Probability", null, true); document.projectform.project_probability.options[1] = new Option("High", 25, true); document.projectform.project_probability.options[2] = new Option("Medium", 10, true); document.projectform.project_probability.options[3] = new Option("Low", 5, true); break; case "prospect": show("probability_select"); document.projectform.project_probability.options[0] = new Option("Probability", null, true); document.projectform.project_probability.options[1] = new Option("High", 50, true); document.projectform.project_probability.options[2] = new Option("Medium", 20, true); document.projectform.project_probability.options[3] = new Option("Low", 10, true); break; case "proposal": show("probability_select"); document.projectform.project_probability.options[0] = new Option("Probability", null, true); document.projectform.project_probability.options[1] = new Option("High", 70, true); document.projectform.project_probability.options[2] = new Option("Medium", 50, true); document.projectform.project_probability.options[3] = new Option("Low", 30, true); break; default: hide("probability_select"); } } function show(layer_ref) { var state = 'visible'; show = document.getElementById(layer_ref); show.style.visibility = state; } function hide(layer_ref) { var state = 'hidden'; show = document.getElementById(layer_ref); show.style.visibility = state
-
Jun 25, 2009, 13:02 #16
- Join Date
- Jun 2009
- Posts
- 53
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
The one-time-only issue was fiixed by nesting the show and hide functions within the getprob() function.
Bookmarks