Adăugați clasa 'has_children' la elementul li părinte când modificați Walker_Nav_Menu

10 mai 2011, 10:46:04
Vizualizări: 38.8K
Voturi: 24

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.

0
Toate răspunsurile la întrebare 4
3
27

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 ) {
            // ...
        }
    }
10 mai 2011 11:45:58
Comentarii

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?

PrivateUser PrivateUser
4 feb. 2012 00:18:13

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

rjb rjb
6 mar. 2013 22:41:15

Mulțumesc mult @Jan fabry.. Eram blocat cu custom walker-ul meu.. În final snippet-ul tău m-a ajutat.

Harish Kanakarajan Harish Kanakarajan
5 mai 2014 13:12:39
2

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!

6 mar. 2013 21:30:09
Comentarii

Eroare fatală: Referința la timpul apelului a fost eliminată în D:\www\wordpress\wp-content\themes\wpt_theme\functions.php la linia 44

Tahir Yasin Tahir Yasin
14 iul. 2014 22:43:55

Linia#44 este parent::start_el(&$output, $item, $depth, $args);

Tahir Yasin Tahir Yasin
14 iul. 2014 22:44:23
1

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.

10 mai 2011 22:36:49
Comentarii

Mulțumesc, deocamdată am nevoie de walker, dar o să mă uit la asta data viitoare!

patnz patnz
11 mai 2011 02:50:17
1

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.

10 mai 2011 11:07:48
Comentarii

Mulțumesc, este pentru un meniu arborescent pliabil pe mai multe niveluri în care introduc și elemente de control, dar cu siguranță e bine să fac cât mai multe cu css!

patnz patnz
11 mai 2011 02:49:02