check_box_tag
check_box_tag(name, value = "1", checked = false, options = {})
public
Creates a check box form input tag.
Options
- :disabled - If set to true, the user will not be able to use this input.
- Any other key creates standard HTML options for the tag.
Examples
check_box_tag 'accept' # => <input id="accept" name="accept" type="checkbox" value="1" /> check_box_tag 'rock', 'rock music' # => <input id="rock" name="rock" type="checkbox" value="rock music" /> check_box_tag 'receive_email', 'yes', true # => <input checked="checked" id="receive_email" name="receive_email" type="checkbox" value="yes" /> check_box_tag 'tos', 'yes', false, :class => 'accept_tos' # => <input class="accept_tos" id="tos" name="tos" type="checkbox" value="yes" /> check_box_tag 'eula', 'accepted', false, :disabled => true # => <input disabled="disabled" id="eula" name="eula" type="checkbox" value="accepted" />
Pass id collections with check box tags
It can be useful to pass a collection of ids to a controller, especially in the case of a has_many relationship, for example:
User has_many Roles
In your view you could have something like:
<ul> <% @roles.each do |role| %> <li> <%= check_box_tag 'role_ids[]', role.id -%> <%= h role.name -%> </li> <% end %> </ul>
Note the square brackets after role_ids - this is important for passing a collection through to the controller.
If you place this in a form and submit it, you can expect to see a param passed into the controller that looks like:
"role_ids"=>["1", "2", "3"]
Delete collections with check box tags
Following autonomous’ directions works wonders on /edit but needs slight modifications when dealing with pagination on /index.
In a /index type listing page we can no longer assume that the list of ids coming back represents changes to all objects so we need to provide some context, that the list of object modifications in our params array is a list of modifications for some set of objects.
We can only assume subsets because pagination or filtering may reduce the set of objects we’re working on.
In our case we had a user management page which listed all users and showed whether they were activated or not. The following code is what we used to ensure that modifications to the first page of objects wouldn’t affect all the other pages.
index.rhtml
<% @users.each do |user| %> <%= hidden_field_tag('seen[]', user.id) -%> <%= check_box_tag 'activated[]', user.id -%> <% end %>
role_controller.rb
def index if request.post? activated_ids = params[:activated].collect {|id| id.to_i} if params[:activated] seen_ids = params[:seen].collect {|id| id.to_i} if params[:seen] if activated_ids seen_ids.each do |id| r = User.find_by_id(id) r.activated = activated_ids.include?(id) r.save end end end end
Use dom_id( resource_instance ) to create the HTML id
In the notes on this page people use:
car_ids_#{c.id}
But you can use this function in stead:
dom_id(c)
Set ids when using a collection of values
The trick to getting the helper to populate a unique HTML ID and for rails to recognise a collection is to give the helper a unique ‘name’ and to set the :name symbol to parameter with an array symbol ‘[]’.
<% Cars.each do |c| %> <%= check_box_tag "car_ids[#{c.id}]", c.id, :name => "car_ids[]" %> <% end %>
Using an unobtrusive Ajax (UJS) :onchange call to the controller#action
An :onchange call can be made using the Rails 3 jquery-ujs helper in the form:
check_box_tag( name, value, checked, html_and_other_options)
For example:
select_tag( "my_tag_id", entity.id, class: "progress bar update_msg", disabled: disabled? data: { remote: true, url: url_for( action: :my_controller_action, id: my_id) // application symbols progress_bar: "progress_bar_div_id", update: "message_div_id" } )
The jquery_ujs looks for data-remote and data-url. These can be spelled-out or placed in the data hash. The url must be formed as select_tag does not call url_for, unlike some of the other related tags. Values for application symbols can also be passed through. jQuery triggers will work on the Ajax events that occur. This generates the following:
<input class="progress_bar update_msg" data-progress-bar="progress_bar_div_id" data-remote="true" data-update="message_div_id" data-url="/my_controller/my_controller_action/my_id" id="my_tag_id" name="my_tag_id" type="checkbox" value="4"/>
In this example, by tying into the events the program makes visible an existing hidden progress bar while awaiting a server response, and then displays a div containing a message returned by the server and hides the progress bar. If the div contains a class= for notice or error, then they will fade out.
$(".layout") .on('ajax:beforeSend', ".progress_bar", function(){ // get id of element to make visible var progress_bar_id = '#' + this.getAttribute('data-progress-bar'); $(progress_bar_id).show(); }) .on('ajax:complete', ".progress_bar", function(){ // get id of element to hide var progress_bar_id = '#' + this.getAttribute('data-progress-bar'); $(progress_bar_id).hide(); }) .on('ajax:complete', ".update_msg", function(evt, xhr, options){ // get id of element to contain message var update = this.getAttribute('data-update'); $("#" + update).replaceWith($(xhr.responseText).attr("id", update)); // cause responses with these classes to fade away... $('.notice').fadeOut(2500); $('.error').fadeOut(8000); });
Set ids when using a collection of values (cont.)
Concerning greeneggs614’s post:
The following version would be a bit more intention revealing while providing the same output:
<% Car.each do |c| %> <%= check_box_tag "car_ids[]", c.id, :id => "car_ids_#{c.id}" %> <% end %>
Set ids when using a collection of values (cont.)
Regarding schmidt’s post.
The following will not have the expected behavior:
<% Car.each do |c| %> <%= check_box_tag "car_ids[]", c.id, :id => "car_ids_#{c.id}" %> <% end %>
But, if you put the “checked” option to false (or true), it will.
<% Car.each do |c| %> <%= check_box_tag "car_ids[]", c.id, false, :id => "car_ids_#{c.id}" %> <% end %>