Tuesday, September 29, 2009

Ruby on Rails : Dynamic Drop down list

First we will look at the html for a basic selection box:

<select name="payment">
<option value="1">VISA</option>
<option value="2">MasterCard</option>
<option value="3">Switch</option>
</select>

It can get quite confusing when it comes to using the different select helpers, select, select_tag and collection_select and in my opinion there is a lack of adequate documentation.

select
select(object, method, choices, options = {}, html_options = {})
Defined in ActionView::Helpers::FormOptionsHelper


º object - name of an instance variable. This is typically a model object (singular name of the table whose data you're displaying, or in other words, the table record).
º method - attribute of that instance variable. This is typically a field/column of the table whose data you're displaying (really an ActiveRecord method).
º choices - can be any enumerable object e.g arrays and hashes and results of database queries, and contains the option tags for the select box.
º options - takes various "options" some of which are listed below in the examples.
º html_options - allows css to be used for styling the select box.

In this example a hash is being used to populate the option tags.

<%= select( "payment", "id", { "Visa" => "1", "Mastercard" => "2"}) %>

Select can be used in conjunction with a model object as seen in this example, an instance variable is passed into choices, but is being converted into an array of arrays.

<%= select ("selected_payment", "id", @payments.map {|u| [u.name,u.id]}) %>

The controller may look something like this:

@payments = Payment.find(:all)
@selected_payment = @payments[2]

This will cause the third option_tag to be selected by default in the select box, but collection_select is preferable in this scenario.
TOP
select_tag
select_tag(name, option_tags = nil, options = {})
Defined in ActionView::Helpers::FormTagHelper


º name - name of the select statement in the generated html, and is used by the controller to access the selected items.
º option_tags - a string containing the option tags for the select box.
º options - takes various "options" some of which are listed below in the examples.

Simple use of the select_tag helper:

<%= select_tag "payment", "<option>VISA</option>" %>

In this example, we are using options_for_select which accepts any container and returns a string of option tags, but we have defined an array. Note how the optional second parameter specifies the selected item in the list.

<%= select_tag "payment", options_for_select([ "VISA", "MasterCard", "Switch" ], "MasterCard") %>

Another option is this

<%= select_tag "payment", options_for_select(%w{ VISA Mastercard Switch }) %>

where %w is the shortcut notation for an array of strings that are space separated.

You can also do multi-select boxes:

<%= select_tag 'payment[]', options_for_select(@payments), :multiple => true, :size => 3 %>

Note that the "name" in this case is an array, and @payments is a hash defined in the controller:

@payments = {'Visa' => 1, 'Mastercard' => 2, 'Switch' => 3}

We can access the selected payment methods in the controller, using the array:

params[:payment]

select_tag does not support the :prompt option, which may not seem like an issue as we have already shown above how you can select a default option tag. But what if you want your form to GET, not POST, your only option is then to use select_tag, even if your data source is a database.

<%= select_tag(:payment, "<option>-Select a payment method</option>" + options_from_collection_for_select(@payments, :name, :name)) %>

As select_tag takes a string, we can concatenate an additional string onto the beginning of the parameter, this allows us to add our default option_tag. We use options_from_collection_for_select which takes a value_method, and text_method (see collection_select for their definition) and an optional selected_value, and a collection, which can be defined in your controller like this:

@payments = Payment.find(:all, :order=>"name")
TOP
collection_select
collection_select(object, method, collection, value_method, text_method, options = {}, html_options = {})
Defined in ActionView::Helpers::FormOptionsHelper


º object - singular name of the table whose data you're displaying (the table record).
º method - field/column of the the relevant data (really an ActiveRecord method).
º collection - takes the option tags for the select box, this can be a hash or array.
º value_method - field/column to use for the value of the option tags in your html.
º text_method - field/column to use for the visible text of the option tags in your html.
º options - takes various "options" some of which are listed below in the examples.
º html_options - allows css to be used for styling the select box.

In this example the payment methods are being added to the select box via a model object, notice how we use the option, :prompt to add an additional option tag to the select box, which will be selected by default. Note that if @object.method matches one of the option tags, this will be selected by default, and :prompt wont appear in the list.

<%= collection_select(:payment, :id, @payments, :id, :name, options ={:prompt => "-Select a payment"}, :class =>"payment") %>

The selected item can be accessed in the controller, by using:

selected_payment = params[payment][id]

A final note: the parameters used in all the helpers may be strings or symbols (symbols may be a better choice in some situations, but that's another article).
TOP
Taken From : http://shiningthrough.co.uk/blog/show/6

5 comments:

  1. Thanks so much. It was very helpful in my project

    ReplyDelete
  2. This is very helpful. Any idea how to make collection_select work for non-numeric ids/keys? Everything works in the view, but upon submit the controller complains with "can't convert String into Integer". The submitted value is an array of strings.

    Thks!

    ReplyDelete
    Replies
    1. <select name="A">
      <option value="B">C</option>
      </select>

      non-numeric ids/keys? Are you asking how to change 'A' or 'B' or 'C' as above, which one are you referring to?

      This is dynamic capturing form value, the output should in array format.

      Thanks.

      Delete
  3. Sorry- the issue as it turns out had nothing to do with the non-numeric values. I'm using the collection_select in a situation where I'm trying to create a HMT association (join model) that has extra attributes. I'm passing the selected items from the collection_select via the collection_singular_ids method, which ignores the additional attributes I need to capture and I was getting the String into Integer error as part of that scenario which I assumed was an issue with the select itself. This is probably beyond the scope you had in mind for this post, so I'll stop here, but if you've ever come across this one, I'd sure like to know how to fix it.
    thx

    ReplyDelete
  4. really Good blog post.provided a helpful information.I hope that you will post more updates like thisRuby on Rails Online Course

    ReplyDelete