Reputation: 99
I'm trying to get my radios and checkboxes to work as buttons w/ the toggle function as seen on twitters bootstrap page. link!
I've somehow managed to get those buttons to appear and function w/ the database, but when If the user returns to the page, they are not toggled. I was wondering if that's is possible or not. If yes, how can I implement that on my code? I'm using simple_form + twitter bootstrap.
Here is the code I'm using to display the radio button:
<div class="btn-group" data-toggle="buttons-radio">
<%= f.input :child_gender, :label => "Child gender?", :collection => [['Boy', 'Boy'], ['Girl', 'Girl'], :as => :radio_buttons, :input_html => { :data => {:toggle => 'buttons-radio'} }, :item_wrapper_class => 'btn btn-toggle btn-small inline' %>
</div>
And here is the code for checkbox button:
<div class="btn-group">
<%= f.input :child_size, :label => "What size?", :collection => child_size, :as => :check_boxes, :input_html => { :data => {:toggle => 'buttons-checkbox'} }, :item_wrapper_class => 'btn btn-toggle btn-small' %>
</div>
Here is the custom css I have for btn-toggle
:
.btn-toggle input {
display: none;
}
Any help is appreciated.
Upvotes: 4
Views: 3344
Reputation: 5076
Building from Nickl's answer and tweaking things to require no additional Javascript and to render the same semantic HTML that Bootstrap currently expects, here's my solution:
class ButtonRadioInput < SimpleForm::Inputs::CollectionRadioButtonsInput
def input
out = '<div class="btn-group" data-toggle="buttons">'
label_method, value_method = detect_collection_methods
collection.each do |item|
value = item.send(value_method)
label = item.send(label_method)
active = ''
active = ' active' unless
out =~ / active/ ||
input_html_options[:value] != value &&
item != collection.last
input_html_options[:value] = value unless active.empty?
btn = 'btn'
btn = "btn btn-#{item.third}" unless item.third.nil?
out << <<-HTML
<label class="#{btn} #{active}">
<input type="radio" value="#{value}" name="#{attribute_name}">#{label}</input>
</label>
HTML
end
out << "</div>"
out.html_safe
end
end
And then to use this you would use SimpleForm as such:
=f.input :role, label: false, as: :button_radio,
collection: [["Warm Up", :warm_up, :primary],
["Small Sided", :small_sided, :primary],
["Expanded", :expanded, :primary],
["Game", :game, :primary]]
This will render code just like the radio-button examples from Bootstrap's own components page.
Upvotes: 4
Reputation: 8731
Here is the missing simple_form
input
we need for the bootstrap radio buttons.
# lib/inputs/button_radio_input.rb
class ButtonRadioInput < SimpleForm::Inputs::CollectionRadioButtonsInput
def input
out = <<-HTML
<div class="btn-group" data-toggle="buttons-radio">
HTML
input_field = @builder.hidden_field(attribute_name, input_html_options)
input_id = input_field[/ id="(\w*)/, 1]
label_method, value_method = detect_collection_methods
collection.each {|item|
value = item.send(value_method)
label = item.send(label_method)
on_click = "document.getElementById('#{input_id}').value='#{value}';return false;"
active = ''
active = ' active' unless
out =~ / active/ ||
input_html_options[:value] != value &&
item != collection.last
input_html_options[:value] = value unless active.empty?
btn = 'btn'
btn = "btn btn-#{item.third}" unless item.third.nil?
out << <<-HTML
<button onclick="javascript:#{on_click}" type="button" class="#{btn}#{active}">#{label}</button>
HTML
}
value = <<-VAL
value="#{input_html_options[:value]}"
VAL
input_field[/value="[^"]*"/] = value.chomp if input_field =~ /value/
input_field[/input/] = "input #{value.chomp}" unless input_field =~ /value/
out << <<-HTML
#{input_field}
</div>
HTML
out.html_safe
end
end
It supports everything as: :radio_buttons
will accept with the addition of an optional 3rd argument for button styles.
= f.input :rad_buttons,
as: :button_radio,
collection: [ [:blue, 1, :primary],
[:red, 2, :danger],
[:green, 3, :success],
]
The haml snippet above will produce a three radio button group
btn-primary
with the label blue
and the value 1
btn-danger
with the label red
and the value 2
btn-success
with the label green
and the value 3
Since we did not assign a value (input_html: {value: 1}
) the last button will be made active (the same behaviour as for normal radio buttons) and the value of rad_buttons
will be 3
nJoy!
Upvotes: 2
Reputation: 1002
You can also use a hidden input field with some unobtrusive JavaScript. Put the hidden field together with the twitter bootstrap toogle buttons in your *.html.erb:
<%= f.hidden_field :child_gender %>
<div id="gender-toggle" class="btn-group" data-toggle="buttons-radio">
<button type="button" class="btn" data-gender="boy">Boy</button>
<button type="button" class="btn" data-gender="girl">Girl</button>
</div>
In your *.js.coffee just set the active button and input value:
# Activate selected gender
$("button[data-gender=" + $('#hidden_field_id').val() + "]").addClass('active')
# Set gender value
$("#gender-toggle button").click ->
$('#hidden_field_id').val($(this).data('gender'))
Hope this helps.
Upvotes: 2