Adăugați clasa 'has_children' la elementul li părinte când modificați Walker_Nav_Menu
Scriu o clasă walker personalizată pentru wp_nav_menu și vreau să pot specifica dacă un element li conține un submeniu. Așadar, vreau ca marcajul meu să fie:
<li class="has_children [alte-clase-wordpress]">
<a class="parent-link">Un element</a>
<ul class="sub-menu">
Știu cum să adaug și să elimin clasele, dar nu găsesc nimic care să-mi spună dacă elementul curent are elemente copil.
Aveți idei?
Mulțumesc anticipat.

Funcția start_el()
ar trebui să primească această informație în parametrul $args
, dar se pare că WordPress completează acest lucru doar dacă $args
este un array, în timp ce pentru meniurile personalizate de navigare este un obiect. Acest lucru este raportat în un tichet Trac. Dar nu e nicio problemă, poți completa tu acest lucru, dacă suprascrii și metoda display_element()
în walker-ul tău personalizat (pentru că acesta este cel mai simplu loc pentru a accesa array-ul de elemente copil):
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 ) {
// ...
}
}

Bună Jan, Poți să mă ajuți cu această întrebare? Am încercat codul tău dar nu am reușit să-l fac să funcționeze. Poți să-mi dai mai multe exemple de cod?

Consultă exemplul complet de implementare mai jos pe această pagină.

Actualizare: Începând cu WordPress 3.7 (octombrie 2013), au fost adăugate clase CSS pentru a indica elementele și paginile copil în meniurile temelor — nu mai este necesar să folosiți un walker personalizat, deoarece acest lucru este gestionat în nucleul WordPress.
Clasele CSS se numesc menu-item-has-children
și page_item_has_children
.
Pentru o soluție completă pentru cei care sunt în grabă (mulțumiri lui Jan Fabry pentru răspunsul anterior), consultați implementarea completă de mai jos.
Afișați navigația în șablonul temei dvs.:
wp_nav_menu( array(
'theme_location' => 'navigation-primary',
'container' => false,
'container_class' => '',
'container_id' => '',
'menu_class' => '',
'menu_id' => '',
'walker' => new Selective_Walker(),
'depth' => 2
)
);
Apoi, includeți următoarele în functions.php
al temei dvs.:
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);
}
}
HTML-ul rezultat va arăta astfel:
<ul>
<li><a href="#">Acasă</a></li>
<li class="has_children"><a href="#">Despre</a>
<ul class="sub-menu">
<li><a href="#">Misiunea noastră</a></li>
</ul>
</li>
<li><a href="#">Servicii</a></li>
<li class="has_children"><a href="#">Produse</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</a></li>
</ul>
Pentru mai multe informații despre utilizarea clasei walker din WordPress, consultați Understanding the Walker Class.
Spor la lucru!

Această funcție este exact ceea ce aveți nevoie. De asemenea, vă arată o modalitate eficientă de a modifica elementele din meniul de navigare. În plus, o puteți extinde pentru funcții mai avansate (de ex. în temele copil) prin intermediul filtrului de elemente:
/**
* Clase pentru un meniu de navigare numit "Topnav" în locația "top".
* Prezintă exemple despre cum să modificați elementul curent din meniul de navigare
*
* @param (object) $items
* @param (object) $menu
* @param (object) $args
*/
function wpse16818_nav_menu_items( $items, $menu, $args )
{
# >>>> începeți editarea
// exemple de ținte posibile
$target['name'] = 'Topnav';
// Elementele de meniu țintite
$target['items'] = array( (int) 6 );
# <<<< opriți editarea
// filtru pentru teme copil: "config_nav_menu_topnav"
$target = apply_filters( 'config_nav_menu_'.strtolower( $target['name'] ), $target );
// Întrerupe dacă nu suntem în meniul numit
if ( $menu->name !== $target['name'] )
return;
foreach ( $items as $item )
{
// Verificați ce conține $item
echo '<pre>'; print_r($item); echo '</pre>';
// Primul exemplu real:
$item->classes = 'span-4';
// Al doilea exemplu real:
// Adaugă această clasă dacă suntem în unul dintre elementele țintite
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 );
Și da, în aproape fiecare caz, nu este nevoie de un walker personalizat.

dacă dorești să creezi un meniu derulant, poți face asta doar cu CSS. creează un meniu personalizat în WordPress cu elemente copil, WordPress atribuie automat clasa .sub-menu pentru elementele ul copil. Încearcă acest CSS:
nav li {position:relative;}
.sub-menu {display:none; position:absolute; width:300px;}
nav ul li:hover ul {display:block;}
Poți adăuga și puțin jQuery pentru a îmbunătăți funcționalitatea, dar codul de mai sus ar trebui să îți ofere un meniu derulant funcțional.
