修改Walker_Nav_Menu时,将“ has_children”类添加到父级li


22

我正在为wp_nav_menu编写自定义的walker类,并希望能够指定li是否包含子菜单。所以我希望我的标记是:

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

我知道如何添加和删除类很好,我只是找不到任何东西告诉我当前项目是否有子项目。

有任何想法吗?

提前致谢。

Answers:


23

start_el()应该在其$args参数中获取此信息,但似乎WordPress仅在$args为array填充此信息,而对于自定义导航菜单,它是一个对象。这是在Trac票中报告的。没问题,如果您还重写display_element()自定义walker中的方法,则可以自己填写(因为这是访问子元素数组的最简单位置):

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,您能帮我解决这个问题吗?我尝试了您的代码,但无法正常工作。您能再给我一些示例代码吗?
吉里(Giri)2012年

请参阅此页面上进一步的完整实现示例
rjb

非常感谢@Jan Fabry ..我被我的定制助行器所困扰..最后,您的代码片段帮助了我。
Harish Chinju 2014年

7

更新:WordPress 3.7(2013年10月)开始,已添加CSS类以指示主题菜单中的子菜单项和页面-无需使用自定义的walker,因为它已在WordPress核心中得到了照顾。

CSS类的名称为menu-item-has-childrenpage_item_has_children


有关匆忙中任何人的完整解决方案(请参见Jan Fabry的先前答案),请参见下面的完整实现。

在主题模板中输出导航:

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

然后,在主题中添加以下内容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);
    }
}

结果HTML输出类似于以下内容:

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

有关使用WordPress的沃克类的更多信息,请参阅了解沃克类

请享用!


致命错误:已在第44行的D:\ www \ wordpress \ wp-content \ themes \ wpt_theme \ functions.php中删除了调用时传递引用
Tahir Yasin

第44行是parent :: start_el(&$ output,$ item,$ depth,$ args);
塔希尔·亚辛

2

该功能正是您想要的。它还向您展示了一种修改导航菜单项的非常有效的方法。此外,您可以通过item-filter打开它以使用更高级的功能(例如,子主题):

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

是的,几乎在每种情况下,都不需要定制的助行器。


谢谢,我现在需要助行器,但是下回合会看看它!
2011年

1

如果要下拉菜单,则只能使用CSS。与孩子一起在WP中自定义导航,WordPress会自动将class .sub-menu分配给孩子ul。试试这个CSS

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

您可能需要添加一些jQuery,以使其更加有趣,但这将为您提供一个有效的下拉菜单。


谢谢,它提供了一个多级可折叠树菜单,我也在其中插入了控制元素,但是对使用CSS尽可能多做绝对有好处!
patnz 2011年

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

3
请说明该代码的作用以及如何回答该问题。
cybmeta

并且请在更多上下文中发布代码。照原样,大多数来访的人都不知道该粘贴到哪里,并且会弄错它。
s_ha_dum
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.