Preserving radio button checked state during drag and drop with jQuery

Have you ever stumbled upon the issue of radio buttons losing their “checked” state while dragging and dropping a div containing them using the Sortable module of jQuery UI? It is not a pleasant experience and is a known issue even in jQuery 1.7.x bundled in WordPress 3.3 – 3.4. Read on to learn how to fix this.

The issue

If you have stumbled upon this, you surely know your way on jQuery so let’s go straight to the point: while using Sortable from jQuery UI, if you drag and drop an element containing radio buttons already checked, they will lose their state (their “checkedness”).

There are a bunch of solutions around, to detect the moment when you start dragging and then dropping, but a bit complicated. I found a solution on WordPress Trac but it was complicated since it requires to register a listener for mouse events and then trigger a click on the radio button that was previously checked.
We don’t need any that: the Sortable module has a callback that is triggered when you start dragging the element so we will use it and we will simply set the checked property on those radio inputs that were checked.
However, this solution was useful in their approach of storing a pointer of only those radio buttons that have been checked.

Fixing it

So let’s consider this code:

[js]
jQuery(document).ready(function ($) {

$(‘#tr-blocks’).sortable({
opacity: 0.5,
helper: ‘clone’,
placeholder: ‘ui-state-highlight’,
start: function (e, ui) {
//The code you need begins here
var radio_checked= {};
$(‘input[type="radio"]’, this).each(function(){
if($(this).is(‘:checked’))
radio_checked[$(this).attr(‘name’)] = $(this).val();
$(document).data(‘radio_checked’, radio_checked);
});
}
}).bind(‘sortstop’, function (event, ui) {
var radio_restore = jQuery(document).data(‘radio_checked’);
for(radio in radio_restore){
$(‘input[id="’+ radio + radio_restore[radio]+’"]’).prop(‘checked’, true);
}
//and ends here
});

});
[/js]

This will save only the names and value of checked radio buttons when user starts dragging using jQuery’s data. When the dragged element is dropped, the data is retrieved and each radio button that was checked before has its checkedness restored using prop.

Now, if you have a keen eye for details, you might have noticed this

[js]
$(‘input[id="’+ radio + radio_restore[radio]+’"]’)
[/js]

why not using the plain ID? like

[js]
$(‘#’+ radio + radio_restore[radio])
[/js]

it was simply because my fields had this notation

[html]
#optionsSetName[subset]value
[/html]

and for some reason using the traditional selector throw an empty array []. Didn’t paid too much attention as it was correctly fixed using the ID attribute, but I just want to clarify that maybe you won’t have to use this selector format.

Another option

Not exactly a fix but an alternative would be to use <select elements. You won’t experience this issue as its checked option is correctly preserved during drag and drop, at least with jQuery 1.7.x.

4 thoughts on “Preserving radio button checked state during drag and drop with jQuery”

Leave a Reply