Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

The codex provides a way to display the children and parent page for use as a sub-menu. However, this code displays the parent page in the list even when the parent has no children. How can I modify this code so it only displays if the parent has pages?

Functions.php

if(!function_exists('get_post_top_ancestor_id')){
/**
 * Gets the id of the topmost ancestor of the current page. Returns the current
 * page's id if there is no parent.
 * 
 * @uses object $post
 * @return int 
 */
function get_post_top_ancestor_id(){
    global $post;

    if($post->post_parent){
        $ancestors = array_reverse(get_post_ancestors($post->ID));
        return $ancestors[0];
    }

    return $post->ID;
}}

Calling it:

<?php wp_list_pages( array('title_li'=>'','include'=>get_post_top_ancestor_id()) ); ?>
<?php wp_list_pages( array('title_li'=>'','depth'=>1,'child_of'=>get_post_top_ancestor_id()) ); ?>
share|improve this question
    
The code I gave you earlier today does what you are looking for here, as near as I can tell. –  s_ha_dum May 18 '13 at 23:57
    
Your code outputs the "Pages" caption and creates an irregular list. –  AndrettiMilas May 19 '13 at 1:12
    
Seriously? Add 'title_li'=> to get rid of the label. You must know that given that you used it in your own code to remove the label. It is a trivial adaptation. No idea what you mean by an "irregular list". The actual list is a nested list generated by WordPress core code. –  s_ha_dum May 19 '13 at 1:41

3 Answers 3

up vote 2 down vote accepted
<?php     
    if ($post->post_parent) { //We are a child, print out sub menu
            wp_list_pages( array('title_li'=>'','include'=>$post->post_parent) );
            wp_list_pages( array('title_li'=>'','depth'=>1,'child_of'=>$post->post_parent) );
    }

//We are not a child but do we have children
$children = wp_list_pages(array('child_of' => $post->ID, 'echo' => 0));

if ( !empty($children) ) {
    //If so print out the sub menu
    wp_list_pages( array('title_li'=>'','include'=>$post->ID) );
    wp_list_pages( array('title_li'=>'','depth'=>1,'child_of'=>$post->ID) );
} 
//Not a child and not a parent so show nothing and continue 
?>

I tested this and it works as you mentioned, I couldn't figure out that function however maybe someone can post a better solution using that function.

share|improve this answer
    
For me, this hid the entire list. –  AndrettiMilas May 18 '13 at 21:12

I took a different route and solved this with CSS. Maybe not as robust, but for a quick fix when needed, here is what I used:

html .main-navigation li.menu-item-263{
    display: none;
}
html .main-navigation li.menu-item-263.menu-item-has-children{
    display: inline-block;
}

Menu item 263 is my parent menu item that sometimes didn't have children (for non-members that aren't logged in because no access to child pages). I guess it breaks if my menu IDs ever change, and I'd have to repeat the CSS to handle other menus... so not perfect, but quick and easy, and not likely to break anything or require a lot of retesting.

Now for the obvious stuff, for the non-developers reading this:

I placed the above in my theme style.css file. To get the menu item ID I just right-click it in FireFox and select "inspect element" -- the ID will be in the class of the menu element. The first 3 lines of the above code hide the menu item with that ID, the last 3 lines override that (display it) if the "menu-item-has-children" class is set (only if it has children).

share|improve this answer

This solution was written by MichaelH at the following link: http://wordpress.org/support/topic/how-to-only-list-pages-if-they-have-no-children.

This does not use list-pages, but get_pages instead, so it may not be 100% relevant. I slightly modified this code with the addition of an exclamation mark before "empty". You can remove it to see how it is working.

<?php
//get all 'first level' pages, then iterate through those results,
//then for each result, see if there are child pages, and if there
//are no child pages for that page, then display
$pages = get_pages('parent=0');
foreach ($pages as $page) {
  $child = get_pages('child_of='.$page->ID);
  if (!empty($child)) {
    ?>
    <li><a href="<?php echo get_page_link($page->ID) ?>"><?php echo $page->post_title;?></a></li>
    <?php
  }
}
?>
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.