How to Create Sortable Checkboxes Option in Customizer


WordPress Customizer is a very powerful. Not only because we have a live preview, but also because it got a lot of build-in input type. And we can also extend it or create our own reuse-able input type.

This is not a full tutorial but only explaining the concept, but you can check the full working code here:

This is a useful control, we can use it for various settings for example:

  • Reorder element, such as header, navigation menu, thumbnail, excerpt, etc.
  • Sharing buttons.
  • etc..

So what we need to do is:

  1. Figure out the data structure to save this settings,
  2. Create custom customizer control.
  3. Use it.

Note: you need to be familiar with Customizer API, and registering your own custom control. If not, you can read this:

Data structure:

In this sortable checkboxes data, we need to save all the checkboxes value (not only the selected checkbox, but all checkboxes), but we also need to save each as active (selected) or inactive (not selected)

for example we have sharing button: Facebook, Twitter, Google+, we can save the data in array:

$data = array(
   'facebook' => true,
   'twitter'  => true,
   'google'   => false,

To make it easier, I prefer to save the data as a string using comma “,” to separate the services (checkboxes) and use colon “:” for inactive/active status for each services. here’s the example data from the array above:


How to save the data:

In this settings, i just create a hidden input, and the value is modified when user change the settings (clicking the checkboxes/sorting it).

Let’s register a custom customizer control:

To do this, we need to load control class in customize_register hook:

add_action( 'customize_register', 'my_customizer_register' );

 * Register
function my_customizer_register( $wp_customize ){

     * Custom Customizer Control: Sortable Checkboxes
     * @link
    class My_Customize_Control_Sortable_Checkboxes extends WP_Customize_Control{

        /* Add functions here. */


    /* Add Section (Optional) */

    /* Add Setting */

    /* Add Control (use the class here) */

Custom Control Class:

This is what we need in the control class:

* Custom Customizer Control: Sortable Checkboxes
* @link
class My_Customize_Control_Sortable_Checkboxes extends WP_Customize_Control{

     * Scripts for this control
    public function enqueue(){
        wp_enqueue_style( 'css-for-this-control' );
        wp_enqueue_script( 'js-for-this-control' );

     * HTML
    public function render_content(){
        /* Bail if no option */
        if ( empty( $this->choices ) ){ return; }

        /* HTML */
        <ul class="my-multicheck-sortable-list">
                    <input name="facebook" type="checkbox" value="1" checked="checked"> Facebook
                <i class="dashicons dashicons-menu"></i>
                    <input name="twitter" type="checkbox" value="1" checked="checked"> Twitter
                <i class="dashicons dashicons-menu"></i>
                    <input name="google_plus" type="checkbox" value="0"> Google+
                <i class="dashicons dashicons-menu"></i>

            <?php /* HIDDEN INPUT TO SAVE THE ACTUAL DATA */ ?>
            <input type="hidden" value="facebook:1,twitter:1,google:0">


“enqueue” function

In this function we can enqueue scripts and styles needed for this control. and it will only loaded when this control is used.

We need to add “jquery” and “jquery-sortable” in our script dependency because we need that to enable user to sort/re-order the checkboxes.

We also need to add “customize-controls” script as dependency. I don’t really know why, but without it, the script will not working properly.

“render_content” function

In this function we can override how customizer render HTML for the settings. As you see above we have extra hidden input to save the real option.

Javacript to Sort and Update Hidden Input

The next part is to make the list of checkboxes sortable, and update the hidden input whenever a user change the value/re-order it.

Make the checkboxes sortable

because we already load “jquery-sortable” script, we can easily use that to make the checkboxes sortable by using the dashicon-menu as the handle:

$( '' ).sortable({
    handle: ' .dashicons-menu',
    axis: 'y',
    update: function( e, ui ){
        $(' input').trigger( 'change' );

We also trigger “change” when user reorder it, we are going to use it to update the value of the hidden input.

Updating the hidden input:

So we need to update the hidden input when “change” action is triggered in the input:

$( " li input" ).on( 'change', function(){

    /* Get the value, and convert to string. */
    this_checkboxes_values = $( this ).parents( '' ).find( 'li input' ).map( function(){
        var active = '0';
        if( $(this).prop("checked") ){
            var active = '1';
        return + ':' + active;
    }).get().join( ',' );
   /* Add the value to hidden input. */
   $( this ).parents( '' ).find( 'input[type="hidden"]' ).val( this_checkboxes_values ).trigger( 'change' );


This will update the hidden input in the format as string format using comma “,” and colon “:” as separator. The “change” trigger to the hidden input is to update the live preview.

So what the JS do:

  1. When sorting the checkboxes, trigger “change” to checkboxes input.
  2. When “change” is triggered to the checkboxes, update the hidden input.
  3. When modifying the hidden input, trigger change to update the live preview.

I create this because i need an easy to use sharing plugin, where my client can sort the order of the sharing button, and I think customizer is the best location to display this settings.

You can download and see the full code in my plugin:

I’m sure there’s a better way to build this feature, if you have a better solution please share in the comment below.

1 Comment

  1. yousif

    how to output value with out usign

    /* === Add share buttons in excerpt and content === */
    if( apply_filters( 'fx_share_display', true ) ){
    add_filter( 'the_excerpt', 'fx_share_filter_excerpt', 99 );
    add_filter( 'the_content', 'fx_share_filter_content', 99 );

Comments are closed.