Adicione a classe 'has_children' ao li pai ao modificar Walker_Nav_Menu


22

Estou escrevendo uma classe walker personalizada para wp_nav_menu e quero poder especificar se um li contém um submenu. Então, eu quero que minha marcação seja:

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

Eu sei como adicionar e remover as classes, mas não consigo encontrar nada para me dizer se o item atual tem itens filhos.

Alguma ideia?

Desde já, obrigado.

Respostas:


23

start_el()deve obter essas informações em seu $argsparâmetro, mas parece que o WordPress preenche isso apenas se $argsfor uma matriz , enquanto para os menus de navegação personalizados é um objeto. Isso é relatado em um ticket Trac . Mas não há problema, você pode preencher isso sozinho, se você também substituir o display_element()método em seu andador personalizado (porque este é o lugar mais fácil para acessar a matriz de elementos filho):

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

Olá Jan, Você pode me ajudar com esta pergunta ? Eu tentei o seu código, mas não consegui fazê-lo funcionar. Você pode me dar mais um código de exemplo?
Giri

Consulte o exemplo completo de implementação mais abaixo nesta página.
Rjb 06/03

Muito obrigado.
Harish Chinju

7

Atualização: a partir do WordPress 3.7 (outubro de 2013), as classes CSS foram adicionadas para indicar itens e páginas do menu filho nos menus de temas - não é necessário usar um andador personalizado, como é tratado no núcleo do WordPress.

As classes CSS são nomeadas menu-item-has-childrene page_item_has_children.


Para uma solução completa para qualquer pessoa com pressa (crédito à resposta anterior de Jan Fabry), consulte a implementação completa abaixo.

Crie a navegação no modelo do seu 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
    )
);

Em seguida, inclua o seguinte no tema 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);
    }
}

A saída HTML resultante será semelhante ao seguinte:

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

Para obter mais informações sobre o uso da classe walker do WordPress, consulte Noções básicas sobre a classe Walker .

Apreciar!


Erro fatal: Chamada-tempo de passagem por referência foi removido em D: \ www \ wordpress \ WP \ conteúdo-temas \ wpt_theme \ functions.php na linha 44
Tahir Yasin

A linha 44 é parent :: start_el (& $ output, $ item, $ depth, $ args);
Tahir Yasin

2

Esta função é exatamente o que você deseja ter. Também mostra uma maneira bastante eficaz de modificar os itens do menu de navegação. Além disso, você pode abri-lo para funções mais avançadas (por exemplo, tema filho) através do filtro de itens:

/**
 * 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 sim, não há - em quase todos os casos - a necessidade de um andador personalizado.


Obrigado, preciso do andador por enquanto, mas vou dar uma olhada nisso na próxima vez!
patnz

1

se você quiser fazer o menu suspenso, poderá fazê-lo apenas com css. Para fazer uma navegação personalizada no WP com filhos, o WordPress atribui automaticamente a classe .sub-menu ao filho ul. Experimente este CSS

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

Você pode adicionar algum jQuery para incrementá-lo um pouco, mas isso deve fornecer um menu suspenso.


Obrigado, é por um menu em árvore dobrável multinível no qual estou inserindo elementos de controle, mas definitivamente é bom fazer o máximo possível com o css!
Patll

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

3
Por favor, explique o que esse código faz e como ele responde à pergunta.
cybmeta

E por favor poste o código em mais contexto. Como é, a maioria das pessoas que as visitam não tem idéia de onde tentar colar isso e entenderá errado.
s_ha_dum
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.