41

I have a form that is an update user form where several of the elements are checkboxes. I want true to pass to the params if checked (this is working) and false to pass to the params if unchecked (not working). The unchecked items are not even being sent to the params. How can i make an unchecked item pass through as false?

Form

<%= form_tag user_url(@user), class: "form-signin", method: 'patch' do %>
 <h4>Please confirm your email.  We'll only email you if you have notifications.</h4>
  <%= email_field_tag :email, current_user.email %>
 <h4>Want to be notified when someone needs a player?  Choose which sports below.</h4>
  <%= check_box_tag :basketball, checked = true %> Basketball</br></br>
  <%= check_box_tag :indoor_volleyball, checked = true %> Indoor Volleyball</br></br>
  <%= check_box_tag :beach_volleyball, checked = true %> Beach Volleyball</br></br>
  <%= check_box_tag :soccer, checked = true %> Soccer</br></br>
  <%= check_box_tag :flag_football, checked = true %> Flag Football</br></br>
  <%= check_box_tag :hockey, checked = true %> Hockey</br></br>
  <%= check_box_tag :kickball, checked = true %> Kickball</br></br>
  <%= check_box_tag :softball, checked = true %> Softball
  <%= hidden_field_tag :user_id, :value => current_user.id %>
  <%= hidden_field_tag :user, :value => current_user %>
 <div>
  </br>
  <%= submit_tag "Submit", class:"btn btn-large btn-success" %>
 </div>

Controller

  def update
   respond_to do |format|
   if @user.update(update_params)
     format.html { redirect_to @user, notice: 'Updates were successful.' }
     format.json { head :no_content }
    else
     format.html { render action: 'edit' }
     format.json { render json: @user.errors, status: :unprocessable_entity }
    end
   end
  end

  def update_params
    params.permit(:email, :soccer, :softball, :beach_volleyball, :indoor_volleyball, :flag_football, :basketball, :hockey, :kickball)
  end
brad
  • 1,675
  • 2
  • 16
  • 23

5 Answers5

83

You need to place a hidden field tag before each checkbox with an empty value, for example:

<%= hidden_field_tag :basketball, '' %>
<%= check_box_tag :basketball, checked = true %> Basketball</br></br>

Then the form is aware it needs to populate that field with an empty value if nothing is selected.

JellyFishBoy
  • 1,658
  • 1
  • 17
  • 25
  • I thought either `check_box_tag` or `f.check_box` did that by default. – Phlip Dec 04 '13 at 16:30
  • 15
    `f.check_box` does that trick for you. But plain ol `check_box_tag` does not. In the case where you are not directly tied to an ActiveRecord model boolean attribute, this is a nice easy solution and basically what `f.check_box` is doing for you. – mr rogers Mar 03 '14 at 01:41
  • I agree with mr rogers, f.check_box did the trick but thanks for the idea JellyFishBoy – vishB Apr 07 '14 at 12:11
5

If anyone have column type boolean and using check_box_tag then look at this. It worked for me. <%= hidden_field_tag :basketball, 'false' %> <%= check_box_tag :basketball, true, is_checked? %>

viks
  • 1,368
  • 16
  • 19
3

Look at it

The main idea to place hidden field before checkbox. When a form is submitted fields will be parsed: if checkbox is checked - its value will be passed, else the value of hidden field

For example smth like this (NOT testes)

<%= hidden_field_tag :basketball, false %>
<%= check_box_tag :basketball, checked = true %> Basketball</br></br>
Community
  • 1
  • 1
gotva
  • 5,919
  • 2
  • 25
  • 35
3

The problem is if you use a hidden attribute before a checkbox and give it the same reference like this:

<%= hidden_field_tag :basketball, false %>
<%= check_box_tag :basketball, checked = true %> Basketball</br></br>

Then if you want to do any type of dynamic action on an attribute, say like $("#basketball").removeAttr("checked") it will target the first instance of $("#basketball") which in this case is the hidden object.

What I ended up doing in my implementation was to add a default value of false to my checkboxes since my default setting was to be unchecked. Then in my jquery I detected a change on the checkbox elements and grabbed the ID of that checkbox. When a change is detected I evaluated the checked property for true or false and set the value attribute accordingly.

$(".checkbox").on('change', function(e) {
  var that;
  that = "#" + e.target.getAttribute("id");
  if ($(that).prop("checked") === true) {
    $(that).val("true");
  }
  if ($(that).prop("checked") === false) {
    return $(that).val("false");
  }
});

When I submit my PUT method form action it is updating the database record correctly with the boolean value even if it is blank.

Ajay Barot
  • 1,681
  • 1
  • 21
  • 37
  • I think in this situation you can still use the `hidden_field_tag`. You just need to specify a different id in the options hash. Since it's only the name attribute that must remain the same between the hidden field and the checkbox. But there might be other concerns I'm not considering. – Jon F. Jun 25 '19 at 18:33
1

It appears that you are able to pass the value. See the following code:

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" />

http://apidock.com/rails/ActionView/Helpers/FormTagHelper/check_box_tag

Kyle
  • 1,058
  • 2
  • 10
  • 22