WordPress offers a range of Widgets by default to include in sidebars. These include Image, Gallery, Recent Posts, Recent Comments, Archives, Text and many others. If you have ever developed a WordPress Theme, you would be familiar with the concept of Custom Widgets. These are widgets specific to a Theme. I would not go in the details about creating a custom widgets as I’m assuming you already know that if you are reading this article. In this article, we’ll be creating a Range Slider Control for a Custom WordPress Widget. I’ll be creating the default slider but each one of them is possible.

This is a developer level article, so I am assuming you have knowledge of developing a WordPress Theme.

I think it’s better to show this by an example. So, I’ll be creating a Custom Widget using a Range Slider Control. So, let’s get started!

The Initial Setup

Firstly, an external file will need to be created where the code for Custom Widget will reside. For the sake of simplicity, let’s save this file in widgets folder in the theme directory. We’ll name this file range-slider.php. This file will need to be included in functions.php file. At the bottom of the functions.php file, add this code-

require get_template_directory() . '/widgets/range-slider.php'.

Now, the file will get included in the theme. In this file we will be creating our custom Widget. The basic code structure for a Custom Widget is as follows-

function indi_range_control_widget() {
    register_widget( 'Indi_Range_Slider' );
}
add_action( 'widgets_init', 'indi_range_control_widget' );

class Indi_Range_Slider extends WP_Widget {

    function __construct() {
     ...setting up Custom Widget...
    }

    public function widget( $args, $instance ) {

     ...front-end of widget...

    }

    public function form( $instance ) {
        
      ...back-end of widget...
    }

    public function update( $new_instance, $old_instance ) {
        
     ...updating the widget on pressing the 'Save' button...
    }
}

To set it up as a Range Slider Widget, we first fill up the __construct() function. It should look like this-

function __construct() {
        parent::__construct(

            // Base ID of your widget
            'indi_range_control',

            // Widget name will appear in UI
            esc_html__('Range Slider Control', 'text-domain'),

            // Widget description
            array( 'description' => esc_html__( 'This Widget will show a Range Slider.', 'text-domain' ), )
        );
    }

Here, we simply specified the ID, the title and the description of the widget. After doing this, you should be able to see a new Widget created in Appearance > Widgets screen.

The form() function

But right now, it will not do anything. It is an empty widget. To make it do things, we need to fill up the widget() and form() functions. While the former controls the front-end of the widget (what appears in the website), the latter creates the controls for the widgets in backend( Appearance > Widgets screen). Will start off by creating the backend of the widget. This is where the structure of the slider is set. Take a look at the code below and paste it in the form() function –

public function form( $instance ) {
      
        $instance = array();
        
        $defaults = array(
	        'title'	=>	esc_html__('Range Slider', 'text-domain'),
	        'value'	=>     '5'
        );
        
        $instance = wp_parse_args( $instance, $defaults );
        
			?>
        <div class="custom_slider_widget_form">
        <label>
            <div class="widget_slider_wrapper">
				<div class="slider_control">
					<h4><?php _e('Range Slider Example', 'text-domain') ?></h4>
					<p>
						<input type="range" class="slider slider_input" name="<?php echo $this->get_field_name('value'); ?>" min="0" max="20" step="1" value="<?php echo esc_attr($instance['value']); ?>" />
						<span class="min">0</span>
						<span class="max">20</span>
					</p>
				</div>
				
				<div class="slide_value">
			        <span class="slide_current slider_display"><?php echo esc_html($instance['value']); ?></span>
			    </div>
			</div>
        </label>
        </div>
            
    <?php
    }

Let’s start from the top. Firstly, the argument $instance is defined as an array. The default values of ‘title’ and ‘value’ are stored in a new $defaults array. It is then parsed with the $instance array. What wp_parse_args does is it merges two arrays in such a way that the values of an array get updated in the second array with the rest of the values of second array remaining unchanged. To read more about it, I recommend this official reference page.

Long story short, if the $instance array already has predefined values, then nothing will happen. If it is the first time the widget is used, the values of $defaults will be placed inside $instance.

Then comes the HTML Markup of a basic HTML Range Slider. You can check it out here. We have added extra <span> tags to show the minimum and maximum values. Also, there is a separate <div> to show the current value of the slider. This is where the current value of the slider is displayed using jQuery. It will not work right now as we have not added jQuery yet. After saving and refreshing the dashboard window, it should look like this-

Adding the Styles

It’s the basic HTML code manifesting itself in the browser. To add extra styling to make it more WordPress friendly, we need to add CSS to it. Since it’s the backend, adding the code to style.css of the theme won’t work. It is only for the front-end. To add custom styles to the backend, WordPress provides an action hook admin_enqueue_scripts. It is comparable to wp_enqueue_scripts. While the latter is used to add styles and scripts to the front-end, the former adds them to the back-end.

We need to create a file called admin.css and place it in a convenient location. For this article, I am adding it in styles folder in the theme directory. After creating the file, we add the following code our theme’s functions.php –

function indi_admin_scripts() {
    wp_enqueue_style('indi-admin-css', get_template_directory_uri() . '/styles/admin.css', true );
}
add_action('admin_enqueue_scripts', 'indi_admin_scripts');

With this, the styles.css loads in the dashboard. Add the following code to the admin.css –

.custom_slider_widget_form input[type="range"] {
  width: 100%;
}
.custom_slider_widget_form .widget_slider_wrapper {
  display: flex;
  align-items: center;
}
.custom_slider_widget_form .widget_slider_wrapper .slider_control {
  width: 75%;
}
.custom_slider_widget_form .widget_slider_wrapper .slide_value {
  display: flex;
  justify-content: center;
  align-items: center;
  position: relative;
  width: 20%;
  height: 45px;
  margin-left: auto;
  background-color: #007fb5;
  border-radius: 3px;
}
.custom_slider_widget_form .widget_slider_wrapper .slide_value span {
  position: absolute;
  color: white;
}
.custom_slider_widget_form .widget_slider_wrapper .max {
  float: right;
}

Not the most elegant code but it works. Add it to admin.css. On adding, refresh the dashboard and it should look as follows –

Saving the value

Now, the slider will work but the value is not updating in the box. Also, the value is not saved on pressing the save button. To save the value, we need to add some code to the update() function in range-slider.php. Add the following code to range-slider.php –

public function update( $new_instance, $old_instance ) {

    $instance['value']   =   ( ! empty( $new_instance['value'] ) ) ? $new_instance['value'] : '';

}

With this, the widget will start saving the value of the range slider. You can check it yourself by outputting it in the front-end. This can be achieved through the widget() function in range-slider.php. Modify the function like this –

public function widget( $args, $instance ) {

	$value	= isset( $instance['value'] ) ? $instance['value'] : '5';
        var_dump( $instance['value']);
		
}

Adding jQuery

This will dump the value of the slider in the front-end. In this code, the default value of slider is set as 5. If nothing is set, 5 will be outputted. On modifying the slider and saving it, the new value gets outputted.

Now, the only thing that remains is making the slider interactive. We need to be able to see the value of the slider as it slides. This is achieved using jQuery. We need to to create another file admin,js. For the sake of simplicity, add it in the styles folder, same as for admin.css and enqueue it. We need to modify the indi_admin_scripts as follows-

function indi_admin_scripts() {
    wp_enqueue_style('indi-admin-css', get_template_directory_uri() . '/styles/admin.css', array(), true );
    wp_enqueue_script('indi-admin-js', get_template_directory_uri() . '/styles/admin.js', array('jquery'), true );
}
add_action('admin_enqueue_scripts', 'indi_admin_scripts');

We just enqueued the admin.js file in the theme. Any code in the file is now rendered in the dashboard. Add the following code to admin.js

jQuery(document).ready(function() {
	
	function getSliders(sliderClass, valClass) {
		
		var Sliders = jQuery('#widgets-right .custom_slider_widget_form').find(sliderClass);
		
		jQuery.each(speedSliders, function() {
			
			var inputVal	=	jQuery(this),
				showVal	= inputVal.parents('.widget_slider_wrapper').find(valClass),
				insertVal = function() {
							showVal.text(inputVal.val() );
						     };
								
			inputVal.on('input', insertVal);
			
		});
	}
	
	//For already Loaded Widgets
	getSliders('.slider_input', '.slider_display');
	
	//For newly added and updated Custom Sliders
	jQuery(document).on('widget-added widget-updated', function(event, widget) {
		
		var inputValue = widget[0].id;
		if ( -1 === inputValue.indexOf('indi_range_control' ) ) {
			return;
		}
		
		//Here, we are sure the custom slider widget is loaded
		var sliderValue		= widget.find('.slider_input'),
		    sliderDisplay	= widget.find('.slider_display');
			
		getSliders(sliderValue, sliderDisplay);
	});
});

This is where the real magic happens! The code is pretty self explanatory. We check for all the instances of the range slider. #widgets-rightmakes sure that only the widgets in sidebar are selected. Then we loop through these every time the slider value changes.

WordPress provides two nifty little events for widgets – 'widget-added' and 'widget-updated'. We use these events to make the sliders work in cases when the range slider is added or updated.

There are many little things happening in this code which, to be honest, I’m too lazy to explain right now 😅. It surely requires another post.

After all this, you should have a perfectly good range slider working which whose value is saved and ready to display at the front-end.

Last Update - December 27th, 2020

Leave a Reply

Your email address will not be published. Required fields are marked *