-
Notifications
You must be signed in to change notification settings - Fork 508
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improved data-remote for checkboxes? #440
Comments
👍 Having the same issue. I'm thinking of just having the form disable the hidden fields when the checkbox is checked. |
👍 cant wait to see a pull request implementing this. |
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. <%=
check_box_tag 'complete', true, task.complete,
onchange: "$(this).data('params', 'complete=' + this.checked)",
data: { remote: true, url: task_path(task), method: :patch }
%> The
jquery-ujs submits the |
If you would like to use rails standards (1 and 0 for checkboxes):
|
Building on the suggestions above, here is an unobtrusive version with a few extra features (appending params and disabling during the request): $(document).on('change.remote-checkbox', 'input[type=checkbox][data-remote=true]', function () {
var $this = $(this)
// Ensure value is a 1 or 0
var value = this.checked * this.checked
// Append value to current params
var currentParams = $this.data('params')
var params = (
(currentParams ? currentParams + '&' : '') +
$this.attr('name') + '=' + value
)
$this.data('params', params) .attr('disabled', true)
}).on('ajax:complete', function () {
$(this).removeAttr('disabled')
}) Given that jQuery's <%= check_box_tag(
'complete',
'1',
task.complete,
data: {
remote: true,
url: task_path(task),
method: :patch,
params: 'another_param=true'
}
) %> With the JavaScript above, the checkbox value will be appended to any existing params. |
(I'm loving seeing these solutions building on each other and evolving). Adding to @domchristie above, if the app uses turbolinks, consider turning off any previous listeners that may have accumulated for the // Remove any accumulated `change.remote-checkbox` event
// listeners before adding the new listener
$(document)
.off('change.remote-checkbox')
.on('change.remote-checkbox', 'input[type=checkbox][data-remote=true]', function() {
var $this = $(this);
// Ensure value is a 1 or 0
var value = this.checked * this.checked;
// Append value to current params
var currentParams = $this.data('params');
var params = (
(currentParams ? currentParams + '&' : '') +
$this.attr('name') + '=' + value
);
$this.data('params', params).attr('disabled', true);
}).on('ajax:complete', function() {
$(this).removeAttr('disabled');
}); |
I think it is generally only necessary to teardown previous listeners when binding to events inside a Unbinding Having said that, the event was name-spaced for this reason, and should probably only be bound to in this one snippet. |
Agreed but this is there for fault tolerance when one of the following happens:
There are other fixes that are possible in these situations, I've just not found any as universal as the |
I'm not sure if I'm just missing something, but the // Remove any accumulated 'change.remote-checkbox' event
// listeners before adding the new listener
$(document)
.off('ajax:before.remote-checkbox')
.on('ajax:before.remote-checkbox', 'input[type=checkbox][data-remote=true]', function() {
var $this = $(this);
// Ensure value is a 1 or 0
var value = this.checked * this.checked;
// Append value to current params
var currentParams = $this.data('params');
var params = (
(currentParams ? currentParams + '&' : '') +
$this.attr('name') + '=' + value
);
$this.data('params', params).attr('disabled', true);
})
.on('ajax:complete', function(event) {
$(event.target).removeAttr('disabled');
}
); |
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 |
Thanks @laverick, small tweak using
|
How do I add data confirm to this? If I used:
The checkbox has changed even if I clicked "Cancel" on the confirmation checkbox . |
@nghoapc It's been a while since my last commit on a rails view, can't help you, but hope that the people here might help you out. Sorry for that. |
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:
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 controllerBut…
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
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 theminimum_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:
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?
The text was updated successfully, but these errors were encountered: