Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save helgatheviking/497b12b18d14db4d0d8bb917fb08a737 to your computer and use it in GitHub Desktop.
Save helgatheviking/497b12b18d14db4d0d8bb917fb08a737 to your computer and use it in GitHub Desktop.
Add an example custom meta field to WordPress menu and display text on front-end (Requires WP5.4)
<?php
/**
* 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 );
?>
<input type="hidden" name="custom-menu-meta-nonce" value="<?php echo wp_create_nonce( 'custom-menu-meta-name' ); ?>" />
<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 );
/**
* 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 );
/**
* 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 );
@nylen
Copy link

nylen commented Feb 26, 2020

@covertnine
Copy link

Thanks for this!

@helgatheviking
Copy link
Author

@photocurio
Copy link

If I want to add custom fields to specific menus (not all menus), how do I do that?

@helgatheviking
Copy link
Author

@photocurio the Menu itself does not seem to be passed anywhere as an argument to the wp_nav_menu_item_custom_fields hook so conditional logic based on the menu seems unlikely. It might maybe be in the $args array... you'd have to check.

My advice would be to leave the fields and just ignore them.

@photocurio
Copy link

@helgatheviking, its true the fields can be overlooked, but if you have a lot of menus, and some menus dedicated for specific purposes, and a lot of data, things can get messy. I'll post if I find a solution.

@helgatheviking
Copy link
Author

@photocurio Fair. I'd try adding additional parameters, var dumping the new params and see what they are:

function kia_custom_fields( $item_id, $item, $args, $menu_id ) {
var_dump($args);
var_dump($menu_id);
}
add_action( 'wp_nav_menu_item_custom_fields', 'kia_custom_fields', 10, 4 );

You might get lucky and have the menu location in the $args array.

@multiplehats
Copy link

Neat example. Thank you!

@whynotadv
Copy link

whynotadv commented Aug 18, 2023

How would I actually show an ACF custom field such as "Location" (which is the address for the Location) in addition to the post title In this area of Wordpress menus??? I need to show the Home Listings location not just the Post Title which is a basic name of the home. Any ideas would be helpful...Then on the frontend in the drop down menu, it would say for example: Northwood • 555 TheCity, State Zip
Screenshot 2023-08-18 at 4 12 56 PM

@helgatheviking
Copy link
Author

Sorry @whynotadv I don't know the answer to that. Does the nav_menu_item_title not apply in the admin?

@whynotadv
Copy link

Thanks @helgatheviking for replying. It might, but I'm not sure. Looks like probably have to use is_admin () https://developer.wordpress.org/reference/functions/is_admin/

I think this is something close, but not sure it's exactly what I'm looking for???? https://developer.wordpress.org/reference/functions/wp_get_nav_menu_items/

@helgatheviking
Copy link
Author

Again, not sure if the wp_get_nav_menu_items in run at this point in the admin either... you'll have to test.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment