1

I've been imagining a piece of functionality that would extend the WordPress drag and drop menu creation. Essentially adding a custom menu item button that would be used to add different types of items other than just links.

I imagine a basic usage as just a text field, but future applications could include adding widget areas inside of a menu item.

Visual Mockup of Idea:

Mockup of base idea

Any information and resources that could help point me to a possible solution would be greatly appreciated.

6
  • Were are you wanting to add this functionality in the menu on the right?
    – Welcher
    Jun 8, 2015 at 16:29
  • @Welcher if you are talking about where would I like to put the code, probably would like to build it into a plugin.
    – Phil Hoyt
    Jun 8, 2015 at 16:40
  • No I meant more along the lines of what you're trying to change.
    – Welcher
    Jun 8, 2015 at 16:41
  • @Welcher Oh I am sorry, that image above is actually just a mockup, Created using firebug and some photoshop.
    – Phil Hoyt
    Jun 8, 2015 at 16:44
  • What have you coded, researched, worked on so far and where are you stuck? Jun 8, 2015 at 16:54

1 Answer 1

2

Super old question I know, but it came up when I was posting a similar question about doing the same thing in the Customizer.

Prior to WordPress 5.4, the only way to add field to the menu items was by replacing the Walker_Nav_Menu_Edit walker with something custom. This had the major downside in that you can only ever have 1 walker and caused a lot of conflicts.

After 8 long years, WP 5.4 introduced the wp_nav_menu_item_custom_fields hook and here is some example code on how to use that hook.

First, we’ll display a text input:

/**
* Add custom fields to menu item
*
* This will allow us to play nicely with any other plugin that is adding the same hook
*
* @param  int $item_id 
* @params obj $item - the menu item
* @params array $args
*/
function kia_custom_fields( $item_id, $item ) {

    wp_nonce_field( 'custom_menu_meta_nonce', '_custom_menu_meta_nonce_name' );
    $custom_menu_meta = get_post_meta( $item_id, '_custom_menu_meta', true );
    ?>
    <div class="field-custom_menu_meta description-wide" style="margin: 5px 0;">
        <span class="description"><?php _e( "Extra Field", 'custom-menu-meta' ); ?></span>
        <br />

        <input type="hidden" class="nav-menu-id" value="<?php echo $item_id ;?>" />

        <div class="logged-input-holder">
            <input type="text" name="custom_menu_meta[<?php echo $item_id ;?>]" id="custom-menu-meta-for-<?php echo $item_id ;?>" value="<?php echo esc_attr( $custom_menu_meta ); ?>" />
            <label for="custom-menu-meta-for-<?php echo $item_id ;?>">
                <?php _e( 'Custom menu text', 'custom-menu-meta'); ?>
            </label>
        </div>

    </div>

    <?php
}
add_action( 'wp_nav_menu_item_custom_fields', 'kia_custom_fields', 10, 2 );

Then we will save the data. Since menu items are a WordPress custom post type, dealing with the data is same as adding and retrieving post_meta a regular post or page.

/**
* Save the menu item meta
* 
* @param int $menu_id
* @param int $menu_item_db_id   
*/
function kia_nav_update( $menu_id, $menu_item_db_id ) {

    // Verify this came from our screen and with proper authorization.
    if ( ! isset( $_POST['_custom_menu_meta_nonce_name'] ) || ! wp_verify_nonce( $_POST['_custom_menu_meta_nonce_name'], 'custom_menu_meta_nonce' ) ) {
        return $menu_id;
    }

    if ( isset( $_POST['custom_menu_meta'][$menu_item_db_id]  ) ) {
        $sanitized_data = sanitize_text_field( $_POST['custom_menu_meta'][$menu_item_db_id] );
        update_post_meta( $menu_item_db_id, '_custom_menu_meta', $sanitized_data );
    } else {
        delete_post_meta( $menu_item_db_id, '_custom_menu_meta' );
    }
}
add_action( 'wp_update_nav_menu_item', 'kia_nav_update', 10, 2 );

Finally, we can displaying some extra text after the menu title.

/**
* Displays text on the front-end.
*
* @param string   $title The menu item's title.
* @param WP_Post  $item  The current menu item.
* @return string      
*/
function kia_custom_menu_title( $title, $item ) {

    if( is_object( $item ) && isset( $item->ID ) ) {

        $custom_menu_meta = get_post_meta( $item->ID, '_custom_menu_meta', true );

        if ( ! empty( $custom_menu_meta ) ) {
            $title .= ' - ' . $custom_menu_meta;
        }
    }
    return $title;
}
add_filter( 'nav_menu_item_title', 'kia_custom_menu_title', 10, 2 );

My full blog post on adding custom fields to WordPress menu items and the full source code

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.