Aggiungi la classe "has_children" al file principale quando modifichi Walker_Nav_Menu


22

Sto scrivendo una classe walker personalizzata per wp_nav_menu e voglio essere in grado di specificare se un li contiene un sottomenu. Quindi voglio che il mio markup sia:

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

So come aggiungere e rimuovere le classi bene, non riesco proprio a trovare nulla che mi dica se l'articolo corrente ha elementi figlio.

Qualche idea?

Grazie in anticipo.

Risposte:


23

start_el()dovrebbe ottenere queste informazioni nel suo $argsparametro, ma sembra che WordPress le riempia solo se $argsè un array , mentre per i menu di navigazione personalizzati è un oggetto. Questo è riportato in un biglietto Trac . Ma nessun problema, puoi riempirlo da solo, se hai anche la precedenza sul display_element()metodo nel tuo walker personalizzato (perché questo è il posto più semplice per accedere all'array di elementi figlio):

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 ) {
            // ...
        }
    }

Ciao Jan, puoi aiutarmi con questa domanda ? Ho provato il tuo codice ma non sono riuscito a farlo funzionare. Puoi darmi qualche altro codice di esempio?
Giri,

Fare riferimento all'esempio completo di implementazione più in basso in questa pagina.
rjb,

Grazie mille @Jan fabry .. Sono stato trattenuto con il mio walker personalizzato .. Atlast il tuo frammento mi ha aiutato.
Harish Chinju,

7

Aggiornamento: a partire da WordPress 3.7 (ottobre 2013), sono state aggiunte classi CSS per indicare voci di menu secondarie e pagine nei menu a tema - non è necessario utilizzare un walker personalizzato come è curato nel core di WordPress.

Le classi CSS sono denominate menu-item-has-childrene page_item_has_children.


Per una soluzione completa per chiunque abbia fretta (merito della risposta precedente di Jan Fabry), vedere l'implementazione completa di seguito.

Stampa la navigazione nel modello del tuo tema:

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

Quindi, includi quanto segue nei temi 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);
    }
}

L'output HTML risultante sarà simile al seguente:

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

Per ulteriori informazioni sull'uso della classe walker di WordPress, vedere Informazioni sulla classe Walker .

Godere!


Errore irreversibile: il pass-by-reference per il tempo di chiamata è stato rimosso in D: \ www \ wordpress \ wp-content \ themes \ wpt_theme \ Functions.php sulla riga 44
Tahir Yasin

La riga # 44 è parent :: start_el (& $ output, $ item, $ depth, $ args);
Tahir Yasin,

2

Questa funzione è esattamente ciò che vuoi avere. Ti mostra anche un modo abbastanza efficace per modificare le voci del menu di navigazione. Inoltre puoi aprirlo per funzioni più avanzate (es. Tema figlio) tramite il filtro degli oggetti:

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

E sì, in quasi tutti i casi non è necessario un walker personalizzato.


Grazie, ho bisogno del walker per ora, ma lo guarderò per la prossima volta!
Patnz,

1

se si desidera effettuare il menu a discesa, è possibile farlo solo con CSS. crea nav personalizzati in WP con i bambini, WordPress assegna automaticamente la classe .sub-menu al bambino ul. Prova questo CSS

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

Potresti voler aggiungere un po 'di jQuery per aromatizzarlo un po', ma questo dovrebbe darti un menu a discesa funzionante.


Grazie, è per un menu ad albero pieghevole multilivello in cui sto inserendo anche elementi di controllo, ma sicuramente buono da fare il più possibile con i CSS!
Patnz,

-1
if ( $this->has_children ) {
    $item_output .= 'has_children';
}

3
Per favore, spiega cosa fa questo codice e come risponde alla domanda.
cybmeta,

E per favore pubblica il codice in più contesto. Come è, la maggior parte delle persone che visitano non hanno idea di dove provare a incollarlo e lo sbaglieranno.
s_ha_dum,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.