Upgrading the Core WordPress Custom Menu Widget

0
11 views

In this article, I walk through upgrading the Custom Menu widget for WordPress to offer the ability to use the Menu Name as the Title for the menu, without the redundancy of having to retype it. I do not hack the core to make these changes. I add code to the functions.php file of a child theme. That code could also be included in a custom plugin if desired.

The good old Custom Menu widget that gets installed with the default WordPress install could use an upgrade wouldn’t you say?

Alright, to be fair, I have actually never used this widget (or any other) until recently, and I have been playing around with WordPress for more than a few years now. So I couldn’t tell you what this widget looked like in version 1, so it may have already seen some wonderful updates, I don’t know. When I first played around with widgets, they felt too “static” to me, so I hand coded “sidebars” (I use the term sidebars loosely like WP does) instead. I use widgets much more now, and definitely appreciate this “modular” approach to web site setup.

At any rate, it was my wife-to-be Amy that shared her opinions about the Custom Menu widget which triggered my idea to do this upgrade and write this article. Amy is brand spanking new to WordPress. Her first web site ever was launched just a few months ago, and she got to tinkering around right away. She played with all the widgets and decided to make some custom menus to show in her sidebars. Then recently she complained that the widget was broken, so I took a peek for myself.

Different Approaches for Using Custom Menus in WordPress

To me, at first glance, the Custom Menu widget worked exactly as expected, at least in how I would use the thing. But Amy represents the average user I would say, so I shut up and listened to what she had to say.

First, let me explain how I would go about using menus, and then I will share her story. After that, I will describe the upgrade that I made to the widget, and walk you through the code to make it happen. The accompanying video shows the steps, and shows the updated widget in action.

Ok, for me, I would create a menu from the Appearance -> Menus section, and maybe call it something like: ‘Primary Menu’ or ‘Top Nav Bar’ or ‘Top Left Sidebar Menu’ or something along those lines. Then, I would just attach that menu to a pre-defined place that my currently installed theme created. I generally wouldn’t go further than that. I would really just use the menus that were created with the theme, or in rare occasions, I would code in a new one.. perhaps for the legal docs like Privacy Policy, Terms and Conditions, etc that I may put in the bottom right side of my footer. To be honest it never really dawned on me to create a menu that could be used within a widget.

However, when peeking at the Custom Menu widget, it seemed straightforward and exactly what someone might want. With it, by default, you can drag it to any pre-defined (again by the theme) widget area, give the section a Title, and then choose a menu to display there. All well and good.

Well… Amy, and perhaps many like her, would look at things slightly different. First off, Amy would call her menus something a little more meaningful. Rather than placement oriented names, she might use names like: ‘Browse by Age’ or ‘Browse by Educational Goal’ for her menus.

She decided to create these menus after playing with the widgets and discovering the Custom Menu widget. That widget, when no menus have been created, will provide a link to the place to create the first menu. Very intuitive. So that’s how she figured all that out. She then went back to the Widget area to place her newly created menu. But remember, she is new to all of this, and Widgets aren’t common-speak for her. Any way… she did as anyone might do, she filled in a title, and chose a menu to attach to that area. And it worked as expected.

The problem came when a few weeks later she wanted to, as she said “rename the menus”. Being new, and not really remembering about Widgets, and how all this was done, she started hovering over the left menu in WordPress to see the different options. She saw “Menu” below “Appearance” and decided, “of course, that’s where I would rename my menus”. Seems logical… but when she changed the name of her menus, and checked her web site sidebar to see the changes, nothing was different. The titles/names were still the same as before.

When she began explaining the issue, I blamed caching right away, and told her to wait a couple minutes and try again. But that wasn’t it at all. The problem was that in order to “rename the menus” she was required to re-title the widget! She couldn’t figure out why on earth her way, which seems very logical, did not work.

I explained that offering the ability to have a custom title for the menu allowed for a lot of flexibility. She argued that she liked her menu names, and they should be the default title when she didn’t want to create a custom one. I decided that was reasonable, so worked on a quick upgrade which is demonstrated below.

Adding a New Form Field to the Custom Menus Widget for WordPress

The first step is adding a new form field to the Custom Menus widget. Realistically we could skip this step and just use the attached menu name anytime the title is left blank. I decided though that since that wouldn’t allow anyone to have blank titles, which is sometimes desired, that it wouldn’t be very flexible of a solution to do it that way.

So, I decided to include a checkbox that says: Use menu name for title when title is left blank?

Which, as is probably obvious, will use the Menu Name as the Title when the checkbox is checked, AND when the Title field is left blank.

Here is the code that could be included in the functions.php file of a child theme, or a plugin perhaps, to include that new form field.

 <?php function tt_add_menu_title_override_option($  widget, $  return, $  instance) {  if ( 'nav_menu' == $  widget->id_base ) {  $  override_title = isset( $  instance['override_title'] ) ? $  instance['override_title'] : ''; ?>  <p>  <input class="checkbox" type="checkbox" id="<?php echo $  widget->get_field_id('override_title'); ?>" name="<?php echo $  widget->get_field_name('override_title'); ?>" <?php checked( true , $  override_title ); ?> />  <label for="<?php echo $  widget->get_field_id('override_title'); ?>">  Use menu name for title when title is left blank?  </label>  </p> <?php  } } add_filter('in_widget_form', 'tt_add_menu_title_override_option', 10, 3 ); ?> 

Note: Please watch the opening and closing php tags. I used them to be “complete” in this example, but you may not need them all when pasting the code to your functions file.

This code above simply places the checkbox, but it does not save it’s “state” (checked or unchecked) but we will do that part in a sec.

This code uses the in_widget_form filter so that we can add HTML to the widget form. At the top I make certain that we are truly working with the Custom Menu widget by checking

 $  widget->id_base 

to see if it is equal to

 nav_menu 

I found ‘nav_menu’ from the WordPress developers area, but you can look through core files as well to see what name to check for if you are working with a different widget.

Then the code checks if the value in the database is set to true or false, then spits out the HTML for the checkbox with the appropriate state.

Next, we will make sure that the checkbox actually works, and the value is saved to the database upon clicking the “Save” button in the widget form.

Saving Custom Data in the Custom Menu Widget Form

Below is the code needed to save the value of the previously created check box.

 <?php function tt_save_menu_title_override_option($  instance, $  new_instance) {  if ( isset( $  new_instance['nav_menu'] ) && !empty( $  new_instance['override_title'] ) ) {  $  new_instance['override_title'] = 1;  }  return $  new_instance; } add_filter( 'widget_update_callback', 'tt_save_menu_title_override_option', 10, 2 ); ?> 

Here we are leveraging the “widget_update_callback” feature so we can save our custom data.

Dynamically Setting the Title for the Custom Menu Widget

Here’s the most important step. This is where we decide what title should be used above the output for the custom menu. If you recall, by default, whatever is in the “Title” field of the Custom Menu widget form will be used. That will still be the case, except in the event the Title is left blank. Normally, when the title field is left blank, no title is displayed. Well, now, with the addition of the new checkbox we added with the code above, we can ask the widget to use the actual name of the menu as the title when this is checked, which seems like a reasonable request. Well, it makes sense for those users who want to visit the “Menu” area in WordPress to update the Titles of their menus that they display using the Custom Menu widget. Here’s the code below. I will explain what it does right after.

 <?php function tt_widget_display_callback($  instance, $  widget, $  args) {  if ( 'nav_menu' == $  widget->id_base && empty($  instance['title']) && $  instance['override_title'] ) {  $  menu_id = $  instance['nav_menu'];  $  nav_menu = wp_get_nav_menu_object($  menu_id);  $  instance['title'] = $  nav_menu->name;  }  $  widget->widget($  args, $  instance);  return false; } add_filter( 'widget_display_callback', 'tt_widget_display_callback', 10, 3 ); ?> 

Here we are working with the widget_display_callback filter which allows our function to be called just before the display of the widget output.

As you can see, at the top of the function we make certain that:

a) we are working with the Custom Menu widget by checking for “nav_menu”
b) the title was left blank
c) and that the “override title” check box is checked (i.e. set to 1 or TRUE)

Then, we get the menu ID, and in turn, determine what the name of the menu is based on that ID.

We then display the modified output.

There are some other nuances to this function, like the need to call the “widget” method, but I am sure that you get the gist of it.

I hope you find this upgrade valuable if your spouse is complaining about the logic of the default WordPress core :)

Related Posts Plugin for WordPress, Blogger...