Get checked status of checkbox in controller - ruby-on-rails

i have a form in my index-view where i create multiple checkboxes. One checkbox for every entry. This looks like this:
index.html.erb
<%= form_for :user, url: usersupdate_path() do |f| %>
<%= render #users %>
<%= f.submit 'test', :class => 'btn btn-primary' %>
<% end %>
_user.html.erb
<%= check_box_tag "checked[#{user.id}]","#{user.id}",true %>
Description:
With the form i want to allow the admin to uncheck users - this users i want to send to the controller and update their attributes.
There are only 2 problems:
1) I have to refresh the site until i can send the form to the controller - i don't know why
2) When i print the array it looks like this:
{"1"=>"1", "2"=>"2", "4"=>"4"}
User 3 was unchecked by me.
What i want is something like this:
{"1"=>"true", "2"=>"true", "3"=>"false", "4"=>"true"}
But how can i send the checked value of the checkbox to the controller?
In my controller i do only this at the moment:
def update
flash[:success] = params[:checked]
redirect_to root_path
end
Thanks

The browser does not serialize an unchecked checkbox when sending form data, so if it is not checked, it never gets sent.
You can generally fix this two ways. Make your action smart enough to see "missing" values as "unchecked", or add a hidden field before each checkbox:
<%= hidden_field_tag "checked[#{user.id}]", "false" %>
<%= check_box_tag "checked[#{user.id}]","#{user.id}", true %>
As for the true-values, the second parameter to check_box_tag is the value you want the checkbox to have, so you can change it to this:
<%= hidden_field_tag "checked[#{user.id}]", "false" %>
<%= check_box_tag "checked[#{user.id}]","true", true %>
And it should do what you want.
Note that if you use FormBuilders they handle this nuance for you.

Related

Rails pass parameter with submit

I have a Rails 3.2.12 app where I would like to pass a parameter via a form submit button.
The param is :invoice_id. In the form the value is in #invoice.
I tried this:
<%= f.submit "Submit", :class => "btn btn-success", params: {:invoice_id => #invoice} %>
In the controller, I would access it like this:
def addinvtimes
#invoice = params[:invoice_id]
But, it ends up being nil.
Thanks for the help!
UPDATE1
That's not how HTML forms work. If there's data that you want to get submitted along with the rest of your form's data but not be viewable or editable by the user, stuff it into a hidden field, like so:
<%= form_for #order do |f| %>
<%= f.text_field :customer_name %>
<%= f.hidden_field :invoice_id, value: #invoice.id %>
<% end %>
When you do this, the invoice_id will be submitted alongside the rest of the form's data, so in this case you would access it as params[:order][:invoice_id].

Rails forms - When no checkboxes are checked, param is not included in POST

I have a Task model, which is joined in a many-to-many relationship with an Objective model.
I have a Task edit form where a user can associate any Objective with a Task via checkboxes. When a checkbox is checked, it should indicate an association between the Task and a particular Objective; when a checkbox is not checked, there should be no association. This should be persisted to the database when the form submits.
<%= form_for #task do |f| %>
<% Objective.all.each do |objective| %>
<%= check_box_tag :objective_ids, objective.id, #task.objectives.include?(objective), :name => 'task[objective_ids][]' %>
<% end %>
<%= f.button :submit %>
<% end %>
Updating a Task seems to work absolutely fine as long as one checkbox is checked by the user, but when the user does not check any checkboxes, the :objective_ids param (which is an array of Objective ids) is not included in the POST action at all. Because of this, when I do #task.update_attributes(params[:task]) in the controller, the Task's collection of Objectives is not updated (i.e. the Task should no longer have any Objectives associated with it, because no checkboxes were checked).
So how can I ensure the :objective_ids param is included in the POST, even if only as an empty array?
Add hidden field above all checkboxes with empty value. It will be sent in case user didn't check any checkboxes.
<%= form_for #task do |f| %>
<%= hidden_field_tag "task[objective_ids][]", nil %>
<% Objective.all.each do |objective| %>
<%= check_box_tag :objective_ids, objective.id, #task.objectives.include?(objective), :name => 'task[objective_ids][]' %>
<% end %>
<%= f.button :submit %>
<% end %>
Here is a good railscasts about this.
You may also want to check the source code for it.

check_box_tag displaying checks incorrectly

I have a form that displays whether tasks are complete or not. You can check the box to set the model's :is_complete attribute to true, and check it again to set it as false. Or so that's how it's supposed to work. I can mark tasks as complete, hit the Update button, and the tasks get marked as complete just fine. But when I try to uncheck the tasks afterwards, nothing gets sent to the update action until I hit the update button again, when they finally get marked as incomplete.
Form
<%= form_tag '/day_tasks/update', :method => :put do %>
<% #day_tasks.each do |day_task| %>
<%= check_box_tag "day_tasks[]", day_task.id, day_task.is_complete? %>
<%= day_task.task.content %><br />
<% end %>
<%= submit_tag "Update" %>
<% end %>
Update action
def update
params[:day_tasks] ||= []
params[:day_tasks].each do |x|
DayTask.find(x).toggle(:is_complete).save
end
redirect_to day_tasks_path
end
I'm pretty sure the issue is with the logic behind displaying whether or not a box is checked ( day_task.is_complete? ) because if I remove that snippet of code, although boxes never appear checked, the tasks are checking and unchecking perfectly fine on the back end. It's only when this snippet is included that I run into the problem of nothing being sent after I hit Update a second time. Any ideas on why this is occurring?
The problem is that a not-checked checkbox will never be sent to the server.
There's a trick: Add a hidden input field with the same name right before the check_box_tag and give it the false value like:
<%= form_tag '/day_tasks/update', :method => :put do %>
<% #day_tasks.each do |day_task| %>
<%= hidden_field_tag "day_tasks[#{day_task.id}]", "0" %>
<%= check_box_tag "day_tasks[#{day_task.id}]", "1", day_task.is_complete? %>
<%= day_task.task.content %><br/>
<% end %>
<%= submit_tag "Update" %>
<% end %>
So now if the check box is not checked, the value will be 0 (false) when the check box is checked, the checkbox "overwrites" the hidden field and sets the value to 1 (true)
You have to adapt your update action since you will get a hash like:
day_tasks[task_id] = 0/1 (not completed / completed)
your update action:
def update
params[:day_tasks] ||= {}
params[:day_tasks].each do |task_id, completed|
DayTask.find(task_id).update_attribute(:is_complete, completed)
end
redirect_to day_tasks_path
end

Rails forms: How to append request params?

I got a list page and I filter items via links with get params (I can choose many links so query would be like "?param1=value1&param2=value2"). But also I have to filter it by text field, so I made a form:
<form>
<%= text_field_tag :zip, params[:zip] %>
<%= submit_tag 'OK', :name => nil %>
</form>
But when I submit it, text field param replaces existing query params. So, how to make text field value add to query, not to replace it?
Since I was just dealing with this problem in Rails 4 I thought I'd share my solution.
My page gets loaded with a sport_id parameter, and when the user specifies a sort-order I wanted it to submit a GET request for page.url/event?sport_id=1&sortby=viewers but it wouldn't preserve the sport_id parameter until I added a hidden field tag in the form like so:
<%= hidden_field_tag :sport_id, params[:sport_id] %>
This solution does submit an empty sport_id parameter if that parameter was not in the original request, but that is easily prevented by encapsulating the hidden field in an <% if params[:sport_id].present? %> condition.
Use hidden_field_tag.
Inside of your form, just set hidden_field_tags for the existing GET params, like so:
<% request.query_parameters.collect do |key, value| %>
<%= hidden_field_tag key, value %>
<% end %>
This will ensure that your existing params persist.
Rails 3?
<%= form_tag your_path(params.except(:controller, :action)), :method => :get do %>
<%= text_field_tag :zip, params[:zip] %>
<%= submit_tag 'OK', :name => nil %>
<% end %>

2 submit buttons in a form

I have a question about forms. I have a fairly standard form that saves a post (called an eReport in my app) with a title and body. The table also has a "published" field, which is boolean. The saved eReport only shows on the public site if this field is set to true, with false being the default.
Rather than the default check box, I would like to display two buttons at the end of the form: a "Publish Now" button and a "Save as Draft" button. If the user presses the former, the published field would be set to true. If the latter, then false. In PHP, I used to display 2 submit fields with different name values, then handle the input with an if/else statement to determine the proper SQL query to build. In Rails, I'm assuming I would place this logic in the controller, under the appropriate action, but I'm not sure how to manipulate the name or id values of buttons.
For the record, I'm using Formtastic, but if someone could show me how to do this with the default Rails form tags, that's OK too. Here's the code for my form as it stands right now:
<% semantic_form_for #ereport do |form| %>
<% form.inputs do %>
<%= form.input :title %>
<%= form.input :body %>
<% end %>
<% form.buttons do %>
<%= form.commit_button :label => "Publish Now" %>
<%= form.commit_button :label => "Save as Draft" %>
<% end %>
<% end %>
Thanks in advance for the help!
I don't know about formtastic, but with the default rails form builder, you could do it like this:
<%= form.submit "Save with option A", :name => "save_option_a" %>
<%= form.submit "Save with option B", :name => "save_option_b" %>
Then in the controller, you can pick those up in params:
if params[:save_option_a]
# do stuff
end
in addition to #iddlefingers answer, here is a view of the log of the application (striping some useless params due to explanation purposes)
Parameters: {"utf8"=>"✓", ..., "comentar"=>"Confirmar"}
where we can see that comentar is the name of the parameter, and "Confirmar" is it's value, which is the button's text too.
which was obtained by submit_tag "Confirmar", :name => 'comentar'
So in general you could have (if you want to reduce the number of params you are working with) several submit_tag "onevalue", :name => 'SAMEname', submit_tag "othervalue", :name => 'SAMEname'...
and retrieve them in your controller
if params[:SAMEname] == "onevalue"
# do stuff
elsif params[:SAMEname] == "othervalue"
#do different stuff
end
I think you need to use jQuery.
You can bind the button click event and submit the form for specified location.

Resources