In our web app, we have a common UI pattern: replacing select lists (eg. drop downs) with a label if there is only one item in the list. For example, when creating a subscription, the user must choose a plan. Normally, there is a list of plans to choose from. However, if there is only one plan that the user can choose, we show a label specifying the one plan they’re getting instead of showing them a list of one.
We implemented this with a custom form builder and a method called select_or_label. It takes the same arguments as select, but only creates the select list if the list of choices has more than one element.
The view looks like:
<% form_for :subscription, :builder => SelectFormBuilder, :url => { :controller => :subscriptions, :action => :create } do |form| -%> <%= form.label :plan %> <%= form.select_or_label :plan_id, Plan.all.collect {|p| [p.name, p.id]} %> <% end -%>
The form builder creates a span and a hidden_field if the size of the choices is 1:
class SelectFormBuilder < ActionView::Helpers::FormBuilder include ActionView::Helpers::TagHelper def select_or_label(method, choices, options = {}) if choices.size == 1 content_tag(:span, choices.first.first) + hidden_field(method, :value => choices.first.last) else select(method, choices, options) end end end
And the spec:
require File.dirname(__FILE__) + '/../spec_helper' describe SelectFormBuilder, :type => :helper do describe "select_or_label" do before do helper = Class.new { include ActionView::Helpers }.new @builder = SelectFormBuilder.new(:subscription, Subscription.new, helper, {}, nil) end it "returns a span and hidden field if the size of the choices array is only one" do html = @builder.select_or_label(:plan_id, [["name", "id"]]) html.should_not have_tag("select") html.should have_tag("span", "name") html.should have_tag("input[type=hidden][name=?][value=?]", "subscription[plan_id]", "id") end it "returns a select if the size of the choices array is greater than one" do html = @builder.select_or_label(:plan_id, [["name", "id"], ["other name", "other_id"]]) html.should_not have_tag("input") html.should have_tag("select[name=?]", "subscription[plan_id]") do with_tag("option[value=?]", "id", "name") with_tag("option[value=?]", "other_id", "other name") end end end end
One Response to “select_or_label with custom form builder”
Sorry, the comment form is closed at this time.




I would go jQuery route to solve this problem.