Archived topic
Display Post's Custom Field In Menu Instead of Navigation Label
13 replies · Started by Eric on March 17, 2021
Hey GP Team! I hope you guys are all doing well...
I have a quick question about using the Generatepress Nav menu. When creating menus I can see that the Nav Menu will change out my navigation label to match the specific post's title. But I wanted to keep my navigation labels different than the titles... and using the "Custom Link" Menu Item allows me to do this, but then does not auto-update when something is changed on that specific post.
How can I display a post's specific custom field (nav_title) instead of the menu's Navigation Label or Post Title? I want my nav menu to defer to displaying the custom field instead of the post title, so that it will also update the nav menu when I change the field on my posts.
Thank you for your time and attention GP Team! I hope to hear from you soon. :-)
Hi there,
You may have to change your walker function as it's baked in on it. https://github.com/tomusborne/generatepress/blob/7b35168f546f83a7abb098a8da3bc0674d49ddeb/inc/structure/navigation.php#L346
you can also try looking for plugins that allow for shortcodes on navigation label text field in Appearance > Menu so you could use ACF shortcodes.
Thank you for your reply Elvin! Ok so I tried the Shortcodes in Menu plugin like you suggested, and it seems to be firing the shortcode correctly but it destroys the look of the Generatepress menu! It will not cascade into a dropdown like the other menu items, even if I set it within the menu hierarchy. It displays the shortcode output in the Generatepress Nav bar area but it appears on top of the menu and breaks the look of the site. I actually just want to swap out the text being used for Navigation Labels with a specific custom field which is assigned per post, so that the site Generatepress nav still looks the same. I've left some screenshot links in Private Information.
Can you link us to the site in question? so we could inspect what's happening.
Since the ACF values are displaying, perhaps we could make it better with custom CSS.
Let us know.
Sure thing, this is the site I am working on today. I've sent it in "Private Information".
Just to mention though, I am actually perfectly happy with using the look of the GP nav menu as it is... just swapping the Post Navigation Label out with the custom field would be perfect for me, even without the shortcode at all. I'm also happier with a solution that doesn't need to rely on a separate plugin too. :)
Can you share the code you've used to build the shortcode? Looks like something might be wrong in there.
Here you go... this is actually the same code Elvin helped me put together last week, but I just wanted to test the custom fields if they would display or not. My goal is really to just have the specific field replace the text in the Navigation Label per post, so that the menu also updates sitewide when I update my posts.
add_shortcode( 'acf_listing', 'acf_listing_func' );
function acf_listing_func($atts) {
$atts = shortcode_atts( array(
'post_type' => 'post',
'posts_per_page' => -1,
'taxonomy' => 'post_tag',
'tax_term' => ''
), $atts, 'acf_listing' );
$no_whitespaces = preg_replace( '/\s*,\s*/', ',', filter_var( $atts['tax_term'], FILTER_SANITIZE_STRING ) );
$tax_term_array = explode( ',', $no_whitespaces );
$args = array(
'post_type' => $atts[ 'post_type' ],
'posts_per_page' => $atts[ 'posts_per_page' ],
'tax_query' => array(
array(
'taxonomy' => $atts[ 'taxonomy' ],
'field' => 'slug',
'terms' => $tax_term_array,
),
),
);
echo '<div class="extraposts"><p style="font-weight:600;">SEE MORE:</p>';
$query = new WP_Query( $args );
while ($query->have_posts()) {
$query->the_post();
$permalink = get_permalink( get_the_ID() );
$thefield1 = get_field('ACF1', get_the_ID() );
$thefield2 = ucfirst(strtolower(get_field('ACF2', get_the_ID() )));
if(!empty($thefield1) || !empty($thefield2)){
echo '<p><a href="'.esc_url( $permalink ).'">'.$thefield1.'</a> - '.$thefield2.'</p>';
}
}
wp_reset_postdata();
echo '</div>';
}
The issue there is that you're using echo in a shortcode function, which requires a return instead.
To get around this, you can add output buffering:
add_shortcode( 'acf_listing', 'acf_listing_func' );
function acf_listing_func($atts) {
ob_start();
if ( is_admin() ) {
return;
}
$atts = shortcode_atts( array(
'post_type' => 'post',
'posts_per_page' => -1,
'taxonomy' => 'post_tag',
'tax_term' => ''
), $atts, 'acf_listing' );
$no_whitespaces = preg_replace( '/\s*,\s*/', ',', filter_var( $atts['tax_term'], FILTER_SANITIZE_STRING ) );
$tax_term_array = explode( ',', $no_whitespaces );
$args = array(
'post_type' => $atts[ 'post_type' ],
'posts_per_page' => $atts[ 'posts_per_page' ],
'tax_query' => array(
array(
'taxonomy' => $atts[ 'taxonomy' ],
'field' => 'slug',
'terms' => $tax_term_array,
),
),
);
echo '<div class="extraposts"><p style="font-weight:600;">SEE MORE:</p>';
$query = new WP_Query( $args );
while ($query->have_posts()) {
$query->the_post();
$permalink = get_permalink( get_the_ID() );
$thefield1 = get_field('ACF1', get_the_ID() );
$thefield2 = ucfirst(strtolower(get_field('ACF2', get_the_ID() )));
if(!empty($thefield1) || !empty($thefield2)){
echo '<p><a href="'.esc_url( $permalink ).'">'.$thefield1.'</a> - '.$thefield2.'</p>';
}
}
wp_reset_postdata();
echo '</div>';
return ob_get_clean();
}
Hi Tom! Thank you so much for your reply...
Unfortunately, when I tried it out I'm still getting the same result, with the shortcode displaying strangely outside of the menu. I've attached a screenshot of how it displays now with your output buffer fix in the "Private information" area.
I think my testing of this particular shortcode might have made things more complicated, because all I really want to do is to swap out the Menu "Navigation labels" with the corresponding ACF field per post. This shortcode was just something Elvin had worked on with me for another part of the site, and is not really meant to be used in the menu. I just used it to test the shortcode plugin solution Elvin suggested.
What I am actually looking for is how to replace the "Navigation label" of the menu with a specific ACF field per post. When I add a "Post" to a menu, It will automatically take my Post title and populate the "Navigation Label" field in the WP backend: https://pasteboard.co/JTspSog.png
I would like to place my ACF field in here instead so that the navigation will auto-update as I edit these fields in the future. I assume it will not work to just place the PHP into this field hehe, but this is sort of what I am trying to do: https://pasteboard.co/JTsrLBL.png
This field would be filled out differently for each post across the site and when I change it on the backend, I am hoping to get it to change as well automatically on the menu.
This sort of thing definitely falls into custom development, but perhaps this will point you in the right direction:
add_filter( 'wp_nav_menu_objects', function( $items, $args ) {
foreach ( $items as $key => $item ) {
if ( 'menuItem: Replace me' === $item->title ) {
$custom_field = get_post_meta( get_the_ID(), 'your_custom_field', true );
if ( $custom_field ) {
$item->title = $custom_field;
} else {
unset( $items[ $key ] );
}
}
}
return $items;
}, 10, 2 );
Then just add this as your menu item title: menuItem: Replace me
Ok I see, Tom! Copy that... Sorry, I thought it would just be a simple filter or something to swap them out... Thank you for the code but this seems to change depending on which post I visit. But the basic functionality is there so I'll keep doing some digging on my own then. Thanks again for the help.
Hey Tom I just wanted to report that I got it to work! I just used "get_field" instead to reference the postID and keep the menu items consistent as I navigate through the site:
add_filter( 'wp_nav_menu_objects', function( $items, $args ) {
foreach ( $items as $key => $item ) {
if ( 'menuItem: Replace me' === $item->title ) {
$custom_field = get_field('ACF1', 123);
if ( $custom_field ) {
$item->title = $custom_field;
}
else { unset( $items[ $key ] );
}
}
}
return $items;
}, 10, 2 );
Thanks again for your help! I am about to go ahead and recreate my nav menu with this, and I am just planning to create several of these functions, one for each post in the menu. I just wanted to ask if having a bunch of these functions stacked one after the other like this... would it be a bad idea to use a bunch, let's say 40 or 50 functions one on top of the other... is this going to be an issue for my GP site speed or security?
I wouldn't say it will cause speed/security issues, but it may be a bit difficult to manage as the list of functions grow.
Glad you got it working :)