I am unsure with some of the configuration options of simple_form in a Rails application: I am using the enum_help plugin https://github.com/zmbacker/enum_help and I display an enum as radio button options.
However the HTML generated wraps radio buttons inside the labels; I would like to have the inputs (radio buttons) first, then the labels.
Current output:
<!-- this is the "label" that seems to be reacting to b.label in the simple form initializer - see below -->
<label class="enum_radio_buttons optional">Rating</label>
<span class="radio radio radio">
<label for="book_rating_favourite">
<input class="enum_radio_buttons optional" type="radio" value="favourite" name="book[rating]" id="book_rating_favourite" />
Favourite
</label>
</span>
<span class="radio radio radio">
...
</span>
...
Desired output:
<label class="enum_radio_buttons optional">Rating</label>
<span class="radio radio radio">
<input class="enum_radio_buttons optional" type="radio" value="favourite" name="book[rating]" id="book_rating_favourite" />
<label for="book_rating_favourite">
Favourite
</label>
</span>
<span class="radio radio radio">
...
</span>
...
I am not quite sure what to do to change this behavior...
EDIT:
I tried to define a custom wrapper but that doesn't seem to work. The "label" is referring to the label of the full radio button group (edited code above for clarity), and so while I was able to change the order and have input first, and label second, the only thing that happened was that the title was BELOW the radio buttons.
Here's the relevant part of config/initializers/simple_form.rb; it seems that b.use :input simply renders the input nested within the individual label...
config.wrappers :enum_radio,
hint_class: :field_with_hint, error_class: :field_with_errors, valid_class: :field_without_errors do |b|
# we need the radio button first, and then the label
# the label should not wrap the button
b.use :html5
b.use :placeholder
b.use :input
# copied from :default wrapper
b.use :hint, wrap_with: { tag: :span, class: :hint }
b.use :error, wrap_with: { tag: :span, class: :error }
end
And here is how I try to use it in the form:
<%= simple_form_for book do |f| %>
<%= render 'shared/form_errors', form: f %>
...
<div class="form-col">
<%= f.input :rating, as: :radio_buttons, wrapper: :enum_radio %>
</div>
...
<% end %>
EnumHelp yields to SimpleForm
So, you'll have to do some SimpleForm customization to achieve this.
Check out custom wrappers as a starting point.
Related
I have a Rails form helper and want to add a css-class to a radio button input field.
<span class="input-nile">
<%= f.radio_button :nile_administration, class: 'input__field input__field-nile radio' %>
<label class="radio-label">Nile Administration</label>
</span>
The output is
<span class="input-nile">
<input type="radio" value="{:class=>"input__field input__field-nile radio"}" name="user[nile_administration]" id="user_nile_administration_classinput__field_input__field-nile_radio">
<label class="radio-label">Nile Administration</label>
</span>
I want to achieve that the input tag of type radio get the css class "radio" like the following:
<span class="input-nile">
<input type="radio" value="" name="user[nile_administration]" class="input__field input__field-nile radio" id="user_nile_administration_classinput__field_input__field-nile_radio">
<label class="radio-label">Nile Administration</label>
</span>
How can i do that?
The issue is with the place of the colon
replace
<%= f.radio_button :nile_administration, class: 'input__field input__field-nile radio' %>
with
<%= f.radio_button :nile_administration , :class => 'input__field input__field-nile radio' %>
Try this:
<%= f.radio_button :nile_administration, '', '', class: 'input__field input__field-nile radio' %>
As mentioned in the docs, radio_button takes its options as the 4th argument:
radio_button(object_name, method, tag_value, options = {})
I think this is work for you:
<span class="input-nile">
<%= f.radio_button :nile_administration,"",class: 'input__field input__field-nile radio', id: 'user_nile_administration_classinput__field_input__field-nile_radio'%>
<label class="radio-label">Nile Administration</label>
</span>
You can set the custom id, classes, and other attributes for the f.radio_button as follows. Because it only takes 3 arguments. That is why using brackets.
<%= f.radio_button :entity_type, 'practice', { checked: true, id: 'entity_type_practice', class: "custom-control-input entity-radio-button" } %>
I have the following Ruby:
<%= simple_form_for #answer, url: presentation_survey_path(#presentation) do |f| %>
<%= f.collection_radio_buttons :option_id, #question.options_array, :first, :last, {label: false} do |b| %>
<div class="col-sm-4">
<%= b.label(class: 'btn btn-large', style: 'margin-right: 20px; margin-left: 20px;') {b.radio_button(id: b.object.last, class: 'answer-input', style: 'display: none;') + b.text } %>
</div>
<% end %>
And it is correctly generating html except that it is generating two labels:
<span>
<label for="answer_option_id_15">
<div class="col-sm-4">
<label class="btn btn-large" for="answer_option_id_15" style="margin-right: 20px; margin-left: 20px;">
<input class="answer-input" id="Way too many" name="answer[option_id]" style="display: none;" type="radio" value="15" />
Way too many
</label>
</div>
</label>
</span>
It is gennerating the first label for some reason. I only want to keep the second one. Label: false is not working. How do I get rid of the first label?
According to the docs:
For check boxes and radio buttons you can remove the label changing
boolean_style from default value :nested to :inline.
In addition, simple_form has some options for collection_radio_buttons that are documented in the code:
# Collection radio accepts some extra options:
#
# * checked => the value that should be checked initially.
#
# * disabled => the value or values that should be disabled. Accepts a single
# item or an array of items.
#
# * collection_wrapper_tag => the tag to wrap the entire collection.
#
# * collection_wrapper_class => the CSS class to use for collection_wrapper_tag
#
# * item_wrapper_tag => the tag to wrap each item in the collection.
#
# * item_wrapper_class => the CSS class to use for item_wrapper_tag
#
# * a block => to generate the label + radio or any other component.
In my case setting item_wrapper_tag to false and boolean_style to :inline did the trick, e.g.:
<%= f.collection_radio_buttons :option_id, #question.options_array, :first, :last, boolean_style: :inline, item_wrapper_tag: false do |b| %>
From an accessibility point of view, it is very important to use fieldset/legend combinations for radio buttons and checkboxes:
fieldset
legend What is your sex?
label for="male" Male
input type="radio" id="male"
label for="female" Female
input type="radio" id="female"
This is even true when being inside a fieldset/legend pair already, like so:
fieldset
legend Personal information
label for="name"
input type="text" id="name"
fieldset // Yes, this is a fieldset inside a fieldset!
legend What is your sex?
label for="male" Male
input type="radio" id="male"
label for="female" Female
input type="radio" id="female"
label for="email"
input type="text" id="email"
Simple_Form automatically generates label elements for these legends, though. Is there an easy way to tell Simple_Form to create fieldset/legends, or do I have to work around this with custom wrappers?
Update
For a first work around, I created a custom wrapper like so:
config.wrappers :vertical_radio_and_checkboxes, tag: 'fieldset', class: 'form-group', error_class: 'has-error' do |b|
b.use :html5
b.optional :readonly
b.wrapper tag: 'legend', class: 'col-sm-3 control-label' do |ba|
ba.use :label # TODO: Doesn't need to be a label tag, see http://stackoverflow.com/questions/29261556/simple-form-use-fieldset-legend-for-radio-buttons-checkboxes
end
b.wrapper tag: 'div', class: 'col-sm-9' do |ba|
ba.use :input
ba.use :error, wrap_with: { tag: 'span', class: 'help-block' }
ba.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
end
end
This is okay for the time being, although I didn't find a way to tell Simple_Form not to generate a label element for the label (which doesn't point to any ID, which implies that it can't be a correct usage anyway, but it has some important CSS classes added to it, so I didn't want to just abandon it and use label_text).
I have added an issue to the Simple_Form-Bootstrap repo: fieldset/legend should be used for multiple checkboxes/radiobuttons.
To prevent the simple_form generated <label> you can use :label => false
for example in your _form.haml:
= f.input :name, :label => false
in your form.
Is that what you want to achieve? Not sure that's is all behind your question.
just in case, there might be some useful info here
I am using validates_acceptance_of :terms, :message => "must be accepted" in my user.rb model, and am using bootstrap-sass.
My check box code looks like this in the view:
<div class="control-group">
<%= f.label :terms, :class => "control-label" do %>
Accept <%= link_to('Terms of Use *', "#myTOUModal", :"data-toggle" => "modal") %>
<% end %>
<div class="controls">
<%= f.check_box :terms %>
</div>
</div>
For some reason, when the terms check box isn't selected on form submission, the appropriate error message shows up at the top of the form, but there is a problem with the field_with_errors div class wrapping around the check box label.
The HTML for the rendered page looks like this:
<div class="control-group">
<label class="control-label" for="user_terms">
Accept Terms of Use *
</label>
<div class="controls">
<input name="user[terms]" type="hidden" value="0" />
<div class="field_with_errors">
<input id="user_terms" name="user[terms]" type="checkbox" value="1" />
</div>
</div>
</div>
The result is that the check box field label isn't highlighted on error. Is there a way to force the div tag placement for the field_with_errors class to show up just after the <div class="control-group"> tag? Why does using a block to define a field label throw off the field_with_errors tag placement? Does anyone have experience with this?
Thank you
This is a bug i think. The problem is in block. Define your label without block and everything works.
Try something like:
<% modal_html = capture do >
Accept <%= link_to('Terms of Use *', "#myTOUModal", :"data-toggle" => "modal") %>
<% end %>
<%= f.label :terms, modal_html, :class => "control-label" %>
Or helper:
def modal_html
#Q{Accept #{link_to('Terms of Use *', "#myTOUModal", :"data-toggle" => "modal")} }.html_safe
end
I don't know why Its not duplicating like the example. When I put the following code to have this form:
<%= simple_form_for(resource, :as => resource_name, :url => registration_path(resource_name), :html => { :class => "form-horizontal" } ) do |f| %>
<%= f.input :user_name, :input_html => { :class => "span3" }, :hint => "just letters and numbers please." %>
<% end %>
Right now it looks like this:
When I want it to be like this (the first example here: http://simple-form-bootstrap.plataformatec.com.br/articles/new).
The Problem lies in the HTML being generated. My HTML is:
<div class="input string optional">
<label for="user_user_name" class="string optional"> User name</label>
<input type="text" size="50" name="user[user_name]" maxlength="25" id="user_user_name" class="string optional span3">
<span class="hint">no spaces or special characters, just letters and numbers please</span>
</div>
And Simple_forms HTML:
<div class="control-group string required">
<label for="article_name" class="string required">
<abbr title="required">*</abbr> Name
</label>
<div class="controls">
<input type="text" size="50" name="article[name]" id="article_name" class="string required span6">
<p class="help-block">add your article title here</p>
</div>
</div>
Totally different. I'm thinking the Bootstrap generator doesn't generate? What do you think? What should I do?
resources
https://github.com/plataformatec/simple_form
https://github.com/rafaelfranca/simple_form-bootstrap
http://simple-form-bootstrap.plataformatec.com.br/
Have you added the initializer for simple_form? this initializer sets the wrappers that should be used to output the bootstrap html
rails generate simple_form:install --bootstrap
Note that this only works with simple_form 2!
The output of
rails g simple_form:install --bootstrap
gives further instructions:
Inside your views, use the 'simple_form_for' with one of the Bootstrap form
classes, '.form-horizontal', '.form-inline', '.form-search' or
'.form-vertical', as the following:
= simple_form_for(#user, :html => {:class => 'form-horizontal' }) do |form|
So you must add the :html => {:class => 'form-horizontal' } option to each _form.html file you want to change the form style. You can use 'form-search', 'form-inline', 'form-horizontal', or 'form-vertical' (the default).
To set the default form to horizontal, edit
lib/templates/erb/scaffold/_form.html.erb
and change the first line to this (using your preferred form class name):
<%%= simple_form_for(#<%= singular_table_name %>, :html => {:class => 'form-horizontal' } ) do |f| %>
For those using HAML, the file path and format will be different.
Is your form css set to "form-horizontal" in outputted HTML?
If not, I think you have to wrap the setting of :html :class in simple_form_for tag like this:
<%= simple_form_for(resource, :as => resource_name, :url => registration_path(resource_name), {:html => { :class => "form-horizontal" }} ) do |f| %>
Hope it helps.
Not sure why you marked #ahmeij's answer as correct.
The correct solution is in your comment - you need to make sure you're using simple_form version 2 and not version 1. Like so:
gem "simple_form", "~> 2.0.0.rc"
or you can do it how sample simple_form bootstrap app on github does it:
gem 'simple_form', git: 'git://github.com/plataformatec/simple_form.git
And incase you didn't run the install the correct command is
rails generate simple_form:install --bootstrap
If you're looking to do this with simple_form v3 rc1 then you can follow the steps I lay out here in my blog. I just researched all of this and implemented it:
http://www.iconoclastlabs.com/blog/using-twitter-bootstrap-3-with-simple_form
copy config\initializers\simple_form.rb to your app,everything will be ok
I tried quite many different solutions but, nothing helped until I've added wrapper: :horizontal_form line to each form inputs. And, I have the latest simple_form version: 3.2.1
For example:
= f.input :payment_term, wrapper: :horizontal_form
Hint: [https://gist.github.com/chunlea/11125126/][1]
For simple_form ('~> 3.5') and bootstrap 4, do the follwing change in simple_form_bootstrap.rb initializer:
config.wrappers :horizontal_form, tag: 'div', class: 'form-group', error_class: 'has-error' do |b|
to
config.wrappers :horizontal_form, tag: 'div', class: 'form-group row', error_class: 'has-error' do |b|
To change all forms to horizontal, do the following change:
config.default_wrapper = :vertical_form
to
config.default_wrapper = :horizontal_form
And to change just one form do this:
<%= simple_form_for(#model, wrapper: :horizontal_form) do |f| %>
Also you may need to replace all occurrences of control-label with form-control-label in initializer to vertically align the labels. Source