1

I'm having difficulty implementing a dropdown menu with Bootstrap and WordPress. I've used filters to add the 'dropdown-toggle-split' class to the link elements of menu items that have submenus. However, after configuring this, the dropdown menu doesn't behave as expected. When I click the first dropdown toggle menu item, all submenus appear, instead of only the submenus of the related menu item. Maybe you can look at this gif:

dropdown toggle all submenus appear

Explanation:

WordPress Filter Usage: I'm using the nav_menu_link_attributes and nav_menu_item_title filters to modify the attributes and content of link elements on menu items that have submenus. My goal is to add the dropdown-toggle-split class to the link elements and change the HTML structure of these menu elements to fit Bootstrap's requirements. Here is the code:

 add_filter( 'nav_menu_link_attributes', function( $atts, $item, $args, $depth ) {
    // Cek jika menu item memiliki submenu

    if ( in_array( 'menu-item-has-children', $item->classes ) ) {
        $args->before = '<div class="btn-group" style="flex-direction: row-reverse;">';
        // $args->before .= '<a href="'.$item->url.'" class="nav-link">'.$item->title.'</a>';
        $atts['class'] .= ' dropdown-toggle dropdown-toggle-split';
        // Tambahkan data-toggle dan aria-haspopup ke atribut
        $atts['data-toggle'] = 'dropdown';
        $atts['aria-haspopup'] = 'true';
    }
    // Kembalikan array $atts yang telah dimodifikasi
    return $atts;
}, 10, 4 );

add_filter( 'nav_menu_item_title', function( $title, $item, $args, $depth ) {
    // Cek jika menu item memiliki submenu
    if ( in_array( 'menu-item-has-children', $item->classes ) ) {
        // Bungkus judul dengan elemen <span> yang memiliki class visually-hidden
        $title = '<span class="visually-hidden">' . esc_html__( 'Toggle Dropdown', 'your-text-domain' ) . '</span>';
        // Tambahkan elemen <a> untuk tautan menu
        $title .= '<a href="' . esc_url( $item->url ) . '" class="nav-link">' . esc_html( $item->title ) . '</a>';
        // Tambahkan div penutup untuk btn-group
        $args->after = '</div>';
    }
    // Kembalikan judul yang telah dimodifikasi
    return $title;
}, 10, 4 );

Because of this code, I get duplicate 'ul dropdown-menu show' with same aria-labelledby="menu-item-dropdown-179".

here is the html elements:

<li id="menu-item-179" class="menu-item menu-item-type-post_type menu-item-object-page current-menu-item page_item page-item-2 current_page_item menu-item-has-children dropdown active menu-item-179 nav-item">
    <div class="btn-group" style="flex-direction: row-reverse;">
        <a href="#" data-toggle="dropdown" aria-expanded="false" class="dropdown-toggle nav-link dropdown-toggle dropdown-toggle-split" id="menu-item-dropdown-179" aria-current="page" aria-haspopup="true">
            <span itemprop="name"><span class="visually-hidden">Toggle Dropdown</span></span>
        </a>
        <a href="http://localhost/wc_course/sample-page/" class="nav-link">Sample Page</a>
    </div>
    <ul class="dropdown-menu show" aria-labelledby="menu-item-dropdown-179">
        <li id="menu-item-187" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-has-children dropdown menu-item-187 nav-item">
            <div class="btn-group" style="flex-direction: row-reverse;">
                <a itemprop="url" href="http://localhost/wc_course/sample-page-2/" class="dropdown-item dropdown-toggle dropdown-toggle-split" data-toggle="dropdown" aria-haspopup="true">
                    <span itemprop="name"><span class="visually-hidden">Toggle Dropdown</span></span>
                </a>
                <a href="http://localhost/wc_course/sample-page-2/" class="nav-link">Sample Page 2</a>
            </div>
            <ul class="dropdown-menu show" aria-labelledby="menu-item-dropdown-179">
                <li id="menu-item-188" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-188 nav-item">
                    <div class="btn-group" style="flex-direction: row-reverse;">
                        <a itemprop="url" href="http://localhost/wc_course/winter-warm-up-sale/" class="dropdown-item"><span itemprop="name">Winter Warm-up Sale</span></a>
                    </div>
                </li>
            </ul>
        </li>
    </ul>
</li>

And this is my javascript file:

import $ from 'jquery';

class scriptNavbar {
    constructor() {
        this.events();
    }

    events() {
        $(document).ready(() => {
            $('.main-menu .dropdown-toggle').on('click', function (e) {
                e.preventDefault();
                // Close other dropdown-menus within the same level
                $(this).closest('.menu-item-has-children').siblings('.menu-item-has-children').find('.dropdown-menu').removeClass('show');
                // Toggle class for the clicked dropdown-menu
                $(this).closest('.menu-item-has-children').find('.dropdown-menu').toggleClass('show');
            });
        
            // Close dropdown-menus when clicking outside of them
            $(document).on('click', function (e) {
                if (!$(e.target).closest('.main-menu .dropdown').length) {
                    $('.main-menu .dropdown .dropdown-menu').removeClass('show');
                }
            });
            // Prevent closing the dropdown-menu when clicking inside it
            $('.main-menu .dropdown-menu').on('click', function (e) {
                e.stopPropagation();
            });
        });        
    }
}

export default scriptNavbar;

I suspect the issue stems from the duplicate 'dropdown-menu show' elements, but I'm unable to find a solution since WordPress Bootstrap NavWalker automatically generates these elements with incremental numbers. Any assistance in resolving this would be greatly appreciated. Thank you in advance for your help!

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Browse other questions tagged or ask your own question.