Custom fields to menu items in WordPress
The wp_nav_menu_item_custom_fields action is called before a nav menu item's move buttons in the menu editor.
The wp_nav_menu_item_custom_fields
action is called before a nav menu item’s move buttons in the menu editor.
Five parameters can be assigned to this hook:
$item_id
$item
$depth
$args
$id
The custom field will appear beneath every menu item if you use the hook as shown below.
<?php
function pe_menu_item_custom_field() {
?>
<div class="pe-mi-custom-field-desc">
<p class="description">
<?php esc_html_e( 'Howdy! Custom fields to menu items in WordPress!', 'projectsengine' ); ?>
</p>
</div>
<?php
}
add_action( 'wp_nav_menu_item_custom_fields', 'pe_menu_item_custom_field' );
Before adding the custom field you should check out the screen options tab at the top. The functionality you want to add might already be available, like the ‘open the link in a new tab‘.
We recommend adding this functionality to a plugin or a child theme.
Let’s add our custom field. It can be anything you want, but we will add a simple checkbox and a text field.
<?php
add_action('wp_nav_menu_item_custom_fields', function($item_id, $item) {
$button = get_post_meta($item_id, '_custom_menu_item', true);
$text = get_post_meta($item_id, '_custom_menu_item_desc', true);
?>
<div class="pe-mi-custom-field-button">
<p class="description">
<label for="pe-mi-custom-field-label-button-<?php echo $item_id; ?>" >
<input type="checkbox"
id="pe-mi-custom-field-button-<?php echo $item_id; ?>"
name="pe-mi-custom-field-button[<?php echo $item_id; ?>]"
<?php checked($button); ?>
/><?php _e('Disable this menu item', 'luckies'); ?>
</label>
</p>
<p class="description">
<label for="pe-mi-custom-field-label-text-<?php echo $item_id; ?>" >
<input type="text"
id="pe-mi-custom-field-text-<?php echo $item_id; ?>"
name="pe-mi-custom-field-text[<?php echo $item_id; ?>]"
value="<?php echo $text; ?>"
/>
</label>
</p>
</div>
<?php
}, 10, 2);
Our custom fields are not saved yet. We will have to add additional functionality, and that is our next step.
WordPress Version: Remember that at least WordPress version 5.4 is necessary for this hook to work.
To be able to save our custom fields, we will need the wp_update_nav_menu_item
hook.
Four parameters can be assigned to this hook:
$menu_id
$menu_item_db_id
$menu_item_data
$fire_after_hooks
<?php
add_action('wp_update_nav_menu_item', function($menu_id, $menu_item_db_id) {
$button = isset($_POST['pe-mi-custom-field-button'][$menu_item_db_id]) && $_POST['pe-mi-custom-field-button'][$menu_item_db_id] == 'on';
update_post_meta($menu_item_db_id, '_custom_menu_item', $button);
$text = isset($_POST['pe-mi-custom-field-text'][$menu_item_db_id]) && $_POST['pe-mi-custom-field-text'][$menu_item_db_id] !== '' ? $_POST['pe-mi-custom-field-text'][$menu_item_db_id] : '';
update_post_meta($menu_item_db_id, '_custom_menu_item_desc', $text);
}, 10, 2);
There are several hooks you can use to tweak the menu items on frontend:
<?php
add_filter('nav_menu_css_class', function($classes, $menu_item) {
$button = get_post_meta($menu_item->ID, '_custom_menu_item', true);
if ($button) {
$classes[] = 'pe-mi-class-disabled';
}
return $classes;
}, 10, 2);