Ajouter la classe 'has_children' au parent parent lors de la modification de Walker_Nav_Menu

22

J'écris une classe de marcheur personnalisée pour wp_nav_menu et je veux pouvoir spécifier si un li contient un sous-menu. Je veux donc que mon balisage soit:

<li class="has_children [other-wordpress-classes]">
    <a class="parent-link">Some item</a>
    <ul class="sub-menu">

Je sais comment ajouter et supprimer des classes, je ne trouve rien qui puisse me dire si l'élément en cours contient des éléments enfants.

Des idées?

Merci d'avance.

    
posée patnz 10.05.2011 - 09:46

5 réponses

23

start_el() devrait obtenir cette information dans son paramètre $args , mais il apparaît WordPress ne le remplit que si $args est un tableau , tandis que pour les menus de navigation personnalisés, il s'agit d'un objet. Ceci est rapporté dans un ticket Trac . Mais pas de problème, vous pouvez le remplir vous-même, si vous redéfinissez également la méthode display_element() dans votre lecteur personnalisé (car il s’agit de l’endroit le plus facile pour accéder au tableau des éléments enfants):

class WPSE16818_Walker extends Walker_Nav_Menu
{
    function display_element( $element, &$children_elements, $max_depth, $depth=0, $args, &$output )
    {
        $id_field = $this->db_fields['id'];
        if ( is_object( $args[0] ) ) {
            $args[0]->has_children = ! empty( $children_elements[$element->$id_field] );
        }
        return parent::display_element( $element, $children_elements, $max_depth, $depth, $args, $output );
    }

    function start_el( &$output, $item, $depth, $args ) {
        if ( $args->has_children ) {
            // ...
        }
    }
    
réponse donnée Jan Fabry 10.05.2011 - 10:45
7

Mise à jour: À partir de WordPress 3.7 (octobre 2013), les classes CSS ont été ajouté pour indiquer des éléments de menu et des pages enfants dans les menus de thèmes - pas besoin d’utiliser un marcheur personnalisé, car il est pris en charge dans le noyau WordPress.

Les classes CSS sont nommées menu-item-has-children et page_item_has_children .

Pour une solution complète pour les personnes pressées (crédit de la réponse précédente de Jan Fabry), voir la mise en œuvre complète ci-dessous.

Générez la navigation dans le modèle de votre thème:

wp_nav_menu( array(
    'theme_location' => 'navigation-primary',
    'container' => false,
    'container_class' => '',
    'container_id' => '',
    'menu_class' => '',
    'menu_id' => '',
    'walker' => new Selective_Walker(),
    'depth' => 2
    )
);

Ensuite, incluez les éléments suivants dans le functions.php de votre thème:

class Selective_Walker extends Walker_Nav_Menu {
    function display_element( $element, &$children_elements, $max_depth, $depth=0, $args, &$output ) {
        $id_field = $this->db_fields['id'];

        if ( is_object( $args[0] ) ) {
            $args[0]->has_children = !empty( $children_elements[$element->$id_field] );
        }

        return parent::display_element( $element, $children_elements, $max_depth, $depth, $args, $output );
    }

    function start_el( &$output, $item, $depth, $args ) {
        if ( $args->has_children ) {
            $item->classes[] = 'has_children';
        }

        parent::start_el(&$output, $item, $depth, $args);
    }
}

La sortie HTML résultante ressemblera à ce qui suit:

<ul>
    <li><a href="#">Home</a></li>
    <li class="has_children"><a href="#">About</a>
        <ul class="sub-menu">
            <li><a href="#">Our Mission</a></li>
        </ul>
    </li>
    <li><a href="#">Services</a></li>
    <li class="has_children"><a href="#">Products</a>
        <ul class="sub-menu">
            <li><a href="#">Lorem Ipsum</a></li>
            <li><a href="#">Lorem Ipsum</a></li>                
        </ul>
    </li>
    <li><a href="#">Contact Us</a></li>
</ul>

Pour plus d'informations sur l'utilisation de la classe de randonneur de WordPress, voir Présentation de la classe Walker .

Profitez!

    
réponse donnée rjb 06.03.2013 - 20:30
2

Cette fonction est exactement ce que vous voulez avoir. Il vous montre également un moyen très efficace de modifier les éléments du menu de navigation. En outre, vous pouvez l’ouvrir pour des fonctions plus avancées (par exemple, thème enfant) via le filtre d’articles:

/**
 * Classes for a navigation named "Topnav" in the nav location "top".
 * Shows examples on how to modify the current nav menu item
 * 
 * @param (object) $items
 * @param (object) $menu
 * @param (object) $args
 */
function wpse16818_nav_menu_items( $items, $menu, $args )
{
    # >>>> start editing

    // examples for possible targets
    $target['name'] = 'Topnav';
    // The targeted menu item/s
    $target['items'] = array( (int) 6 );

    # <<<< stop editing

    // filter for child themes: "config_nav_menu_topnav"
    $target = apply_filters( 'config_nav_menu_'.strtolower( $target['name'] ), $target );

    // Abort if we're not with the named menu
    if ( $menu->name !== $target['name'] ) 
        return;

    foreach ( $items as $item )
    {
        // Check what $item contains
        echo '<pre>'; print_r($item); echo '</pre>';

        // First real world example:
        $item->classes = 'span-4';

        // Second real world example:
        // Append this class if we are in one of the targeted items
        if ( in_array( (int) $item->menu_order, $target['items'] ) )
            $item->classes .= ' last';
    }

    return $items;
}
add_filter( 'wp_get_nav_menu_items', 'wpse16818_nav_menu_items', 10, 3 );

Et oui, dans presque tous les cas, vous n'avez pas besoin d'un marcheur personnalisé.

    
réponse donnée kaiser 10.05.2011 - 21:36
1

si vous voulez faire du menu déroulant, vous pouvez le faire avec css uniquement. faire une navigation personnalisée dans WP avec des enfants, WordPress assigne automatiquement la classe .sub-menu à l'enfant ul. Essayez ce CSS

    nav li {position:relative;}
   .sub-menu {display:none; position:absolute; width:300px;}
    nav ul li:hover ul {display:block;}

Vous pouvez ajouter un peu de jQuery pour le pimenter légèrement, mais cela devrait vous donner un menu déroulant fonctionnel.

    
réponse donnée alexndm 10.05.2011 - 10:07
-1
if ( $this->has_children ) {
    $item_output .= 'has_children';
}
    
réponse donnée yaroslav 13.11.2015 - 19:20

Lire d'autres questions sur les étiquettes