Description
Background
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?