Fügen Sie die Klasse 'has_children' zum übergeordneten li hinzu, wenn Sie Walker_Nav_Menu ändern

22

Ich schreibe eine angepasste Walker-Klasse für wp_nav_menu und möchte angeben können, ob ein li ein Untermenü enthält. Daher möchte ich, dass mein Markup wie folgt lautet:

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

Ich weiß, wie man die Klassen gut hinzufügt und entfernt. Ich kann einfach nichts finden, um mir zu sagen, ob das aktuelle Element untergeordnete Elemente enthält.

Irgendwelche Ideen?

Danke im Voraus.

patnz
quelle

Antworten:

23

start_el()sollte diese Informationen in seinem $argsParameter erhalten, aber es scheint, dass WordPress dies nur ausfüllt, wenn $argses sich um ein Array handelt , während es sich bei den benutzerdefinierten Navigationsmenüs um ein Objekt handelt. Dies wird in einem Trac-Ticket gemeldet . Aber kein Problem, Sie können dies selbst ausfüllen, wenn Sie auch die display_element()Methode in Ihrem benutzerdefinierten Walker überschreiben (da dies der einfachste Ort ist, um auf das untergeordnete Elementarray zuzugreifen):

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 ) {
            // ...
        }
    }
Jan Fabry
quelle
Hallo Jan, kannst du mir bei dieser Frage helfen ? Ich habe Ihren Code ausprobiert, aber ich konnte ihn nicht zum Laufen bringen. Können Sie mir noch einen Beispielcode geben?
Giri
Lesen Sie das vollständige Implementierungsbeispiel weiter unten auf dieser Seite.
rjb
Vielen Dank @Jan fabry .. Ich wurde mit meinem Custom Walker aufgehalten .. Atlast Ihr Schnipsel hat mir geholfen.
Harish Chinju
7

Update: Ab WordPress 3.7 (Oktober 2013) wurden CSS-Klassen hinzugefügt, um untergeordnete Menüelemente und Seiten in Themenmenüs anzuzeigen. Es ist nicht mehr erforderlich, einen benutzerdefinierten Walker zu verwenden, da dieser in WordPress Core behandelt wird.

Die CSS-Klassen heißen menu-item-has-childrenund page_item_has_children.


Eine vollständige Lösung für alle, die es eilig haben (dank der vorherigen Antwort von Jan Fabry), finden Sie in der folgenden vollständigen Implementierung.

Gib die Navigation in der Vorlage deines Themas aus:

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

Nehmen Sie dann Folgendes in Ihr Thema auf functions.php:

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);
    }
}

Die resultierende HTML-Ausgabe sieht folgendermaßen aus:

<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>

Weitere Informationen zur Verwendung der Walker-Klasse von WordPress finden Sie unter Grundlegendes zur Walker-Klasse .

Genießen!

rjb
quelle
Schwerwiegender Fehler: Die Pass-by-Referenz für die Anrufzeit wurde in D: \ www \ wordpress \ wp-content \ themes \ wpt_theme \ functions.php in Zeile 44
Tahir Yasin,
Zeile 44 ist parent :: start_el (& $ output, $ item, $ depth, $ args);
Tahir Yasin
2

Diese Funktion ist genau das, was Sie haben möchten. Es zeigt Ihnen auch eine ziemlich effektive Möglichkeit, Navigationsmenüelemente zu ändern. Darüber hinaus können Sie es über den Item-Filter für erweiterte (zB untergeordnete) Funktionen öffnen:

/**
 * 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 );

Und ja, in fast allen Fällen ist kein maßgefertigter Gehwagen erforderlich.

Kaiser
quelle
Danke, ich brauche den Walker fürs Erste, werde ihn mir aber für das nächste Mal ansehen!
patnz
1

Wenn Sie Dropdown erstellen möchten, können Sie dies nur mit CSS tun. Benutzerdefinierte Navigation in WP mit untergeordneten Elementen erstellen, WordPress weist der untergeordneten ul automatisch das Untermenü der Klasse zu. Versuchen Sie dieses CSS

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

Vielleicht möchten Sie etwas jQuery hinzufügen, um es ein wenig aufzupeppen, aber dies sollte Ihnen ein funktionierendes Dropdown-Menü geben.

alexndm
quelle
Danke, es ist für ein mehrstufiges Baummenü, in das ich auch Steuerelemente einfüge, aber definitiv gut, um so viel mit CSS wie möglich zu tun!
patnz
-1
if ( $this->has_children ) {
    $item_output .= 'has_children';
}
Jaroslaw
quelle
3
Bitte erklären Sie, was dieser Code bewirkt und wie er die Frage beantwortet.
Cybmeta
Und bitte posten Sie den Code in mehr Kontext. So wie es ist, werden die meisten Besucher keine Ahnung haben, wo sie versuchen sollen, das einzufügen, und werden es falsch verstehen.
s_ha_dum