Improved data-remote for checkboxes?
See original GitHub issueBackground
I have a form that I want to save automcatically via ajax as the options are changed. In particular, I want to have a checkbox that turns on/off a feature (“student booking”, in this example).
Problem
I do something like this in my view:
= f.check_box :student_booking, data: { url: schedule_path, remote: true, method: :patch }
= f.select :minimum_notice, minimum_notice_options, {}, data: { url: schedule_path, remote: true, method: :patch }
The minimum notice attribute will be sent to the controller each time it’s changed. Yay!
And when check the student_booking
attribute, that updated value will be sent to the controller
But…
When they uncheck the student_booking
attribute, UJS will send an empty request to the controller because unchecked checkbox values don’t get sent in HTML forms (grrr… don’t get me started on this decision!).
The empty request contains no parameters. So a common controller method like this
def schedule_params
params.require(:schedule).permit(:student_booking, :minimum_notice)
end
will choke (400 Bad Request) because there’s no required schedule parameter.
And worse, we can’t assume that the absence of the student_booking
parameter means that it’s been turned off because when the minimum_notice
attribute was updated, it didn’t send the checkbox attribute either.
A Proposed Solution
It’s a common pattern to force unchecked checkbox values to be sent using this:
= hidden_field_tag "schedule[student_booking]", false
= f.check_box :student_booking
If the checkbox is unchecked, the hidden field value will be sent instead.
Could, or more importantly, should UJS support this pattern? i.e., if the checkbox has been unchecked, check for a hidden input field of the same name, and submit that value to the controller.
As it is currently, I feel data-remote
is not functional for checkboxes. In fact, it’s deceptive because it works when checking the item, but not unchecking it.
Thoughts?
Issue Analytics
- State:
- Created 8 years ago
- Reactions:9
- Comments:13
Not a PR I’m afraid but a workaround that will be appropriate for some scenarios.
The workaround is isolated to the checkbox markup so the controller never has to know that unchecking checkboxes can be troublesome.
The
onchange
JS updates thedata-params
attribute of the checkboxinput
:data-params
will becomplete=true
when the checkbox is checked.data-params
will becomplete=false
when the checkbox is unchecked.jquery-ujs submits the
data-params
attribute value in the AJAX request when the checkbox is clicked.If you have trouble getting the in-line template code from @eliotsykes & @rafaelcgo working with Rails 5.1 you may want to try vanilla JS instead of jQuery.
(Note the difference to
onchange:
. I suspect this may be due to rails-ujs, but don’t quote me on that.)