adding display none based on post status in walker menu

122 Views Asked by At

I'm trying to add a display:none to a walker menu in functions but it's not working.

Basically if post status is "draft" then...

Any ideas where I've gone wrong?

            if ( isset( $item->classes[0] ) && ! empty( $item->classes[0] ) ) {
                $custom_class_data = ' data-classes="' . $item->classes[0] . '"';
            }

            $class_names = $class_names ? ' class="' . esc_attr( $class_names ) . $class_columns . '"' : '';

            $style = $style ? ' style="' . esc_attr( $style ) . '"' : '';

            $id = apply_filters( 'nav_menu_item_id', 'menu-item-' . $item->ID, $item, $args );
            $id = $id ? ' id="' . esc_attr( $id ) . '"' : '';
            global $post;
            $page_id = $post->ID;; // example id of your page 
            $page = get_page( $page_id );
            if( $page->post_status == 'draft' ) : 
            $output .= '<li role="menuitem" style="display: none"' . $id . ' ' . $class_names . ' ' . $column_width . $custom_class_data . $style . ' >';
            else:
            $output .= '<li role="menuitem" ' . $id . ' ' . $class_names . ' ' . $column_width . $custom_class_data . $style . ' >';
            endif;
            $output .= apply_filters( 'walker_nav_menu_start_el', $item_output, $item, $depth, $args );

        } // End if().
2

There are 2 best solutions below

1
On

You already have $style variable that stores styles, I would do something like that:

// code...
if( $page->post_status == 'draft' )  {
    $style = 'display: none;';
    // if $style was previously initialized
    // $style += 'display: none;';
}
$style = $style ? ' style="' . esc_attr( $style ) . '"' : '';
$output .= '<li role="menuitem"' . $id . ' ' . $class_names . ' ' . $column_width . $custom_class_data . $style . ' >';
// rest of the code
4
On

You are using global $post to check for the status, but that refers to the current page, so it won't work properly.

Hide the menu item in the nav

I assume this is in the start_el function, and the $item variable passed in has the details of the page/post to add to the menu, so you can check the status directly like this:

if( $item->post_status == 'draft' )

Your updated code would be:

if ( isset( $item->classes[0] ) && ! empty( $item->classes[0] ) ) {
    $custom_class_data = ' data-classes="' . $item->classes[0] . '"';
}

$class_names = $class_names ? ' class="' . esc_attr( $class_names ) . $class_columns . '"' : '';

$style = $style ? ' style="' . esc_attr( $style ) . '"' : '';

$id = apply_filters( 'nav_menu_item_id', 'menu-item-' . $item->ID, $item, $args );
$id = $id ? ' id="' . esc_attr( $id ) . '"' : '';

if( $item->post_status == 'draft' ) : 
    $output .= '<li role="menuitem" style="display: none"' . $id . ' ' . $class_names . ' ' . $column_width . $custom_class_data . $style . ' >';
else:
    $output .= '<li role="menuitem" ' . $id . ' ' . $class_names . ' ' . $column_width . $custom_class_data . $style . ' >';
endif;
$output .= apply_filters( 'walker_nav_menu_start_el', $item_output, $item, $depth, $args );


Alternative: Don't include the link at all in the nav

As they are just draft pages you shouldn't include them at all - display:none just hides them from the display they are still included in the HTML, so the urls can easily be seen by checking the HTML, and Google will still try to follow the links.

I'd suggest checking the status as the first thing in your function, and if its draft, return wothout doing anything, otherwise process the item as normal.

function start_el( &$output, $item, $depth = 0, $args = array(), $id = 0 ) {
    // don't add page/post if it is draft
    if( $item->post_status == 'draft' ) return;

    // if its not draft, process as normal
    [...]

}


Note: Posts with other statuses

Draft posts are not normally included so I assume you are using custom code to get the posts/pages to display. In that case, don't forget about posts with a status of future, private or trash also.