Custom dropdown field in wordpress menus

It's always better to add the functionality to your WordPress theme 'in the code'. This code will give you the ability to have a dropdown field in your menus.

It happens more often than not that you stumble upon a new and neat functionality in your work, by necessity. In my case the necessity was adding icons to the WordPress menus. So after a bit of googling around I found a code made by Weston Ruter, about custom fields in the WordPress menu. I modified his code, and was happy with the results. After a while a question came up on stackoverflow, to add a dropdown field to the menus where you’ll be able to choose the megamenu size on the menus. There are tons of solutions out there, and if you ask somebody chances are that he’ll recommend a plugin solution.

Plugins are a valid way to add a functionality to your site … But they can often be heavy, and if you include too much of them on your site, there is a good possibility that your website will become slow. And google doesn’t love slow sites.

Plugins are a valid way to add a functionality to your site, and that is their first intention. But they can often be heavy, and if you include too much of them on your site, there is a good possibility that your website will become slow. And google doesn’t love slow sites (ref1) (ref2). Being a web developer that spent over a year in developing themes for Themeforest, I guess I got used to the fact that I need to code as much functionality as I can, to avoid slowing the site down. This poured over into my client work that I do now. I’ll admit sometimes it’s easier to get a working plugin that will save you hours of coding and researching, but even so, I always try to code as much as possible inside the theme I’m creating for a client.

One of the possibility of adding the megamenu dropdown is described in this gist. While this approach works, it has its drawbacks. First of all, you need to add the dropdown with Javascript. That means that when you add a page to your menu you won’t see a thing (since adding page in WordPress menu page is done with AJAX and there is no page reload). So you need to add a page, save it and only then you’ll see a dropdown with megamenu description. And that’s a bad UX practice (if you don’t have a tutorial that explains this functionality the chances are that you’ll miss it altogether). I knew that I can add additional fields to my menus (mostly input fields), which meant that there has got to be a way to include this dropdown menu as well.

But there was a catch (there always is). Input fields are different than select dropdown. When you write in the input field, the contents are readily available to the global $_POSTvariable on save. And having just a select dropdown won’t give you that option. So I added one hidden input field where my selected option will be. That way I will be able to put that option in the $_POSTvariable, and save it to the post meta (WordPress treats menu items as special kind of posts).

Megamenu part

First you’ll need to have a menu_walker.phpfile, where you’ll put your custom menu walker. I’ll put the entire code of my walker file below.

First, you’ll add an action with the custom class for adding additional fields. You can read more about adding an action with the class here. You need to create an options array with the HTML look of your new field. This can be input field, dropdown, or a custom field of your choice. You’ll notice the addition of the hidden input field. This is where we store the value of our select.

Next you add a setup function that will have save action, filters that handle the editing and adding the additional fields, and a description of your field in the options array (you are pulling the names, labels etc. from it).

Now one thing that was unnecessary was that I defined ‘mega’ fields that I later pulled in each option. I was trying out how to use WordPress native selected() function, but I had no luck and just forgot to remove it. So you can just remove

from the _add_fields() function, and you’ll just remove the curly brackets from your options to look like this: <option value="mega1">Mega Menu - Single Column</option>. The last function is the one that saves our option in the post meta with our key and value. You’ll also need this extension

that will just put the new field before the default description field.

Javascript part

Ok, so after we’ve added this, we need the javascript that will put our values from the selected box into the hidden input field. This is where Javascript comes to the rescue

We need this, because it’s our hidden input field that will save the option we need. This is all cool, but how do we use it? Well you need your custom walker for this. I’ll paste the content of my entire  menu_walker.php file

Full code

You’ll need to copy the entire code, I’ve only shown the 30 lines (because it’s rather big chunk of code). Either click on the ‘Toggle plain code’ button in the upper right or click on the ‘Copy’ button. In it you have code to allow HTML in the description box, megamenu, and adding sidebars to the menu (which is a cool thing to combine with megamenus).

Now the way we add megamenus is basically by adding a classes to our list items. First we get the post meta for each menu item (I said that the menu items are posts)

a check to see if we have a megamenu or not

and then we build our html

The last part you’ll need is the css that will make it all work on the front end, which is an exercise I leave to you.

menu dropdown field wordpress backend

A working dropdown field on the menu pages in the menu item.

And there you have it. A cool way to add any kind of extra field to your menu pages. Hope this help, if it does or you have any kind of questions, just leave them in the comment below :)


Also published on Medium.

Join the Discussion

  • CircuitoX

    Thanks for this tutorial, this help me a lot to add custom field dropdown I really I appreciate all your work.

  • roberto solini

    Denis your tutorial are very useful. Hope you’ll continue.
    When I use your code I’ve got

    Strict Standards: Declaration of my_custom_Walker_Nav_Menu_Edit::start_el() should be compatible with Walker_Nav_Menu_Edit::start_el(&$output, $item, $depth = 0, $args = Array, $id = 0)
    so
    I’ve changed function start_el(&$output, $item, $depth, $args) { to function start_el(&$output, $item, $depth = 0, $args = array() , $id = 0) {
    and
    parent::start_el($item_output, $item, $depth, $args);
    $new_fields = apply_filters( ‘my_custom_nav_menu_item_additional_fields’, ”, $item_output, $item, $depth, $args);
    to
    parent::start_el($item_output, $item, $depth, $args, $id = 0);$new_fields = apply_filters( ‘my_custom_nav_menu_item_additional_fields’, ”, $item_output, $item, $depth, $args, $id );

    • Yeah, it’s an old piece of code, it should be (where the definition of the class is and the start_el() function): start_el( &$output, $item, $depth = 0, $args = array(), $id = 0 )

  • roberto solini

    Hi denis Thanks for this tutorial but I have a problem.
    I didn’t get any mega class menu added to my code.
    For exemple if I choose mega menu 3 column for commande.
    I get this in the inspector https://uploads.disquscdn.com/images/d08603860f10f47c42f086d31db7bc325751eeb5c780b5a396c4ef0604155f1f.png

    • Hi! Did you include the JavaScript code? It is essential, since you’ll add the correct value in the hidden field using JS. That field will then add the necessary class in the menu walker.

      • roberto solini

        Yes since you said ‘ Add this in a separate .js file that you’ll include only on nav-menus.php page’ on SO I write :
        function pw_load_scripts($hook) {

        if( $hook != ‘nav-menus.php’ )
        return;
        wp_enqueue_script( ‘megamenu’, get_template_directory_uri() . ‘/assets/js/megamenu_admin.js’ , array(‘jquery’), ‘1’ , true);
        }
        add_action(‘admin_enqueue_scripts’, ‘pw_load_scripts’);

        in my function.php and I include the menu walker with require_once :

        require_once (‘inc/menu_walker.php’);

        • And are you sure that the `megamenu_admin.js` is loaded on the menus page? Try to inspect the menus page and see if it is loaded. If it is, please post a question on SO, it’s a lot easier to answer it there :)

  • michel lompret

    Denis I have a question to modify the start_lvl. I would add sf-mega class to the ul like that and avoid have the two div for the mega menu but I have some problem to modify the start_lvl function. I open a SO question here https://stackoverflow.com/questions/46263444/modify-start-lvl-function

    If you could say me what you think about it, it would be great :D

    • Hi Michel! I answered on your SO question. Sadly this cannot be done, at least not from within the php. You could scan the class on the front using javascript and then just paste it to the wrapper…

      • michel lompret

        Ok Thanks for your answer