2

How do I add custom fields to a specific menu?

For example, I have menu "Primary" with ID 13. How do I run the wp_nav_menu_item_custom_fields hook only if ID matches the currently selected menu?

I tried getting the ID from the $id parameter of the hook, but it always returns 0. I'm trying to check the ID like this:

function add_menu_field( $item_id, $item, $depth, $args, $id ) {
    var_dump( $id );
}

add_action( 'wp_nav_menu_item_custom_fields', 'add_menu_field', 10, 5 );

This returns int(0) but my nav menu ID is 13. Am I using this hook incorrectly, or is there another way to get the ID? My goal is to put custom fields on a specific nav by checking the ID.

Thanks for any help!

2
  • Seems like you're looking for a generic PHP code like if ( 13 === $id ) { // add your field }. Commented Nov 15, 2020 at 0:27
  • @SallyCJ Yes but how can I compare $id if it always returns 0. Commented Nov 15, 2020 at 0:54

2 Answers 2

2

Am I using this hook incorrectly

No, you're not.

is there another way to get the ID?

Yes, try this:

function add_menu_field( $item_id, $item, $depth, $args, $id ) {
    $id2 = 0;

    if ( ! $id && isset( $_GET['menu'] ) && $_GET['menu'] ) {
        $id2 = absint( $_GET['menu'] );
    }
    elseif ( ! $id && ! isset( $_GET['menu'] ) ) {
        // Get recently edited nav menu.
        $id2 = absint( get_user_option( 'nav_menu_recently_edited' ) );

        if ( ! is_nav_menu( $id2 ) ) {
            $nav_menus = wp_get_nav_menus();
            $id2 = ( ! empty( $nav_menus ) ) ? $nav_menus[0]->term_id : 0;
        }
    }

    if ( 13 === $id2 && is_nav_menu( $id2 ) ) {
        echo '<hr>add your awesome custom field here';
    }
}

And that's basically how WordPress gets the ID on the wp-admin/nav-menus.php (Appearance → Menus) page — if there's no selected menu ($_GET['menu'] is not set), we use the recently edited menu, if any; if none, we use the first menu in the available nav menus.

Alternate Option (use a filter to add the action)

You can use wp_edit_nav_menu_walker to add your action to wp_nav_menu_item_custom_fields whereby the action (i.e. the hook callback) would simply display the custom field. For example:

add_filter( 'wp_edit_nav_menu_walker', 'wpse_378190', 10, 2 );
function wpse_378190( $class, $menu_id ) {
    $tag = 'wp_nav_menu_item_custom_fields';
    if ( 13 === $menu_id && ! has_action( $tag, 'add_menu_field2' ) ) {
        add_action( $tag, 'add_menu_field2', 10, 5 );
    }

    return $class;
}

// This function is hooked to wp_nav_menu_item_custom_fields and fires only if the
// menu ID is 13. So no need to check the $id and just display your custom field.
function add_menu_field2( $item_id, $item, $depth, $args, $_id ) {
    $id = 13;
    echo '<hr>display your awesome custom field here';
}
1

As I was searching for this answer and could not find a working resolution, thought I would comment here so others can have the answer

function wcd_add_nav_item_field($item_id, $item) {
    // Get the global menu variable that holds the current menu being edited
    global $nav_menu_selected_id;

    // Menu ID to check against
    $menu_id = 'main-menu'; // Replace with your menu ID if different

    // Check if current menu is assigned to menu_id location
    if (isset($locations[$menu_id]) && $locations[$menu_id] == $nav_menu_selected_id) {
        
        // Add the custom field to the menu item

    }


}
add_action('wp_nav_menu_item_custom_fields', 'wcd_add_nav_item_field', 10, 2);

I have added a working checkbox function to the following source:

/*
* WP Version: 6.7.2
*/

// Add the checkbox to the menu item custom fields only for main-menu
function wcd_add_product_categories_checkbox($item_id, $item) {
    // Get the global menu variable that holds the current menu being edited
    global $nav_menu_selected_id;
    
    // Get all menu locations
    $locations = get_nav_menu_locations();
    
    // Menu ID to check against
    $menu_id = 'main-menu'; // Replace with your menu ID if different

    // Check if current menu is assigned to menu_id location
    $is_menu_id = false;
    if (isset($locations[$menu_id]) && $locations[$menu_id] == $nav_menu_selected_id) {
        $is_menu_id = true;
    }
    
    // Only show the checkbox if it's the menu_id
    if ($is_menu_id) {
        wp_nonce_field('add_product_categories_nonce', '_add_product_categories_nonce_name');
        $checked = get_post_meta($item_id, '_add_product_categories', true);
        ?>
        <p class="field-add-product-categories description description-wide">
            <label for="edit-menu-item-add-product-categories-<?php echo $item_id; ?>">
                <input type="checkbox" id="edit-menu-item-add-product-categories-<?php echo $item_id; ?>" name="menu-item-add-product-categories[<?php echo $item_id; ?>]" <?php echo checked($checked, 'on', false); ?> />
                <?php esc_html_e('Add Product Categories as Submenu', 'your-theme'); ?>
            </label>
        </p>
        <?php
    }
}
add_action('wp_nav_menu_item_custom_fields', 'wcd_add_product_categories_checkbox', 10, 2);

// Save the checkbox data when updating the menu item
function wcd_save_product_categories_checkbox($menu_id, $menu_item_db_id) {
    if (!isset($_POST['_add_product_categories_nonce_name']) || !wp_verify_nonce($_POST['_add_product_categories_nonce_name'], 'add_product_categories_nonce')) {
        return;
    }

    // Check if the checkbox was ticked
    if (isset($_POST['menu-item-add-product-categories'][$menu_item_db_id])) {
        $checked = 'on';
    } else {
        $checked = 'off';
    }

    // Save the checkbox value in post meta for the menu item
    update_post_meta($menu_item_db_id, '_add_product_categories', $checked);
}
add_action('wp_update_nav_menu_item', 'wcd_save_product_categories_checkbox', 10, 2);
0

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.