Walker_Nav_Menuを変更するときに、親liに「has_children」クラスを追加します


22

wp_nav_menu用にカスタマイズされたwalkerクラスを作成しており、liにサブメニューが含まれているかどうかを指定できるようにしたいと考えています。だから私は私のマークアップが欲しいです:

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

私はクラスをうまく追加したり削除したりする方法を知っています。現在のアイテムが子アイテムを持っているかどうかを教えてくれるものを見つけることができません。

何か案は?

前もって感謝します。

回答:


23

start_el()$argsパラメータでこの情報を取得する必要がありますが、WordPress $argsは配列である場合にのみこれを埋めるように見えますが、カスタムナビゲーションメニューの場合はオブジェクトです。これはTracチケットで報告されます。ただしdisplay_element()、カスタムウォーカーでメソッドをオーバーライドする場合は、これを自分で埋めることができます(子要素配列にアクセスする最も簡単な場所であるため):

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、この質問で私を助けてくれますか?私はあなたのコードを試しましたが、それを機能させることができませんでした。サンプルコードを教えてください。
ギリ

このページのさらに下の完全な実装例を参照してください。
rjb

@Jan fabryに感謝します。私はカスタムウォーカーに耐えられました。
ハリッシュCh州

7

更新:のようにワードプレス3.7(2013年10月)、CSSクラスは、テーマのメニューに子メニュー項目やページを示すために追加されていない-それはWordPressのコアでの世話をしていますようにカスタム歩行器を使用する必要が。

CSSクラスの名前はmenu-item-has-childrenおよびpage_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のwalkerクラスの使用の詳細については、Walkerクラスについてを参照してください。

楽しい!


致命的エラー:44行目のD:\ www \ wordpress \ wp-content \ themes \ wpt_theme \ functions.phpで呼び出し時の参照渡しが削除されました
タヒルヤシン

Line#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 );

そして、はい、ほぼすべての場合において、カスタムウォーカーは必要ありません。


おかげで、今はウォーカーが必要ですが、次回はこれを見ていきます!
patnz

1

ドロップダウンを作成したい場合は、cssでのみ実行できます。WPで子を持つカスタムナビゲーションを作成すると、WordPressは自動的にクラス.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

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

3
このコードの機能と質問への回答方法を説明してください。
サイブメタ

そして、より多くのコンテキストでコードを投稿してください。現状では、訪問するほとんどの人はどこに貼り付けようとしているのか分からず、間違ってしまいます。
s_ha_dum
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.