Adding Custom Options to Existing Widgets

Sometimes it’s easier and more efficient to add functionality to an existing widget instead of creating a similar widget from scratch. In this three part series, we’re going to look at how to extend the existing WordPress Custom Menu widget to allow menu item descriptions to be displayed. This is part one of a three part series. Here are the posts in this series:

Getting Started

I did a lot of searching through blogs, forums, and WordPress core before finally figuring out how to accomplish this. It probably took me three hours to write just 30 lines of code. Hopefully this guide will make the process shorter for you!

There are two parts to adding a widget option in the dashboard: displaying the option, and saving the option. Let’s look at them in order.

Displaying a Custom Widget Option

To display a custom form option, we attach our function to the “in_widget_form” filter.

function thmfdn_add_menu_description_option( $widget, $return, $instance ) {

	// Are we dealing with a nav menu widget?
	if ( 'nav_menu' == $widget->id_base ) {

		// Display the description option.
		$description = isset( $instance['description'] ) ? $instance['description'] : '';
		?>
			<p>
				<input class="checkbox" type="checkbox" id="<?php echo $widget->get_field_id('description'); ?>" name="<?php echo $widget->get_field_name('description'); ?>" <?php checked( true , $description ); ?> />
				<label for="<?php echo $widget->get_field_id('description'); ?>">
					<?php _e( 'Show descriptions', 'thmfdn_textdomain' ); ?>
				</label>
			</p>
		<?php
	}
}
add_filter('in_widget_form', 'thmfdn_add_menu_description_option', 10, 3 );

As you can see, this function accepts three parameters. Here are the descriptions of the parameters taken from WordPress core:

$widget WP_Widget The widget instance, passed by reference.
$return null Return null if new fields are added.
$instance array An array of the widget’s settings.

In the code above, the first thing we do is check the $widget->id_base to make sure we’re dealing with a custom menu widget. If you’re trying to add a new option to a different widget, then you’ll need to change “nav_menu” to whatever the base ID is for your widget.

Hint: You can echo $widget->id_base at the top of the function above to display each widget’s base ID at the bottom of each widget options form.

Next we determine whether or not the description option has been previously set. Then we output the checkbox for our option, followed by the label. Finally, we add our function to the “in_widget_form” filter. We should now see a description option at the bottom of the widget options form of the Custom Menu widget.

Menu Description Checkbox

Saving a Custom Widget Option

To save a custom widget option, we will attach a new function to the “widget_update_callback” filter.

function thmfdn_save_menu_description_option( $instance, $new_instance ) {

	// Is the instance a nav menu and are descriptions enabled?
	if ( isset( $new_instance['nav_menu'] ) && !empty( $new_instance['description'] ) ) {
		$new_instance['description'] = 1;
	}

	return $new_instance;
}
add_filter( 'widget_update_callback', 'thmfdn_save_menu_description_option', 10, 2 );

This function takes two parameters.

$instance array The current widget instance’s settings.
$new_instance array Array of new widget settings.

We start by checking to make sure that the nav_menu array element has been set. This is to determine that we’re working with a Custom Menu widget. This prevents is from saving our “description” setting to every widget. If you’re working with a different widget, you’ll need to examine the $new_instance array to find a unique field to check.

Next we check to see if our description setting contains a value. If both of our checks come back positive, we set the description item of the $new_instance array to 1. This ensures that the only possible values that make it into the database are 1 and null.

Lastly, we return the new instance.

At this point, we should have a working checkbox in the Custom Menu widget options form in the WordPress back end. As this series progresses, we’ll learn how to make use of that option on the front end.