0

I am using this Bootstrap 4 Navwalker, bs4navwalker, to step through my WordPress menu items and generate a navbar, like...

Single level - works

    <?php
    wp_nav_menu([
      'menu'            => 'primary',
      'theme_location'  => 'primary',
      'container'       => 'nav',
      'container_class' => 'sidebar-nav',
      'menu_id'         => 'sidebarnav',
      'depth'           => 2,
      'fallback_cb'     => 'bs4navwalker::fallback',
      'walker'          => new bs4navwalker()
    ]);
    ?>

This correctly generates a navbar like ...

enter image description here

<nav class="sidebar-nav">
    <ul id="sidebarnav" class="menu">
        <li id="menu-item-3" class="menu-item menu-item-type-custom menu-item-object-custom current-menu-item current_page_item menu-item-home menu-item-3 nav-item active">
            <a title="Home Page" target="_blank" href="http://sandbox.contexthq.com/" class="nav-link active" aria-expanded="false">
                <i class="icon-speedometer"></i>Home Page
            </a>
        </li>
        <li id="menu-item-4" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-4 nav-item">
            <a title="Example Page" target="_blank" href="http://example.com/" class="nav-link" aria-expanded="false">
                <i class="ti-layout-grid2"></i>Example Page
            </a>
        </li>
        <li id="menu-item-5" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-5 nav-item">
            <a title="Custom Page" target="_blank" href="http://example.com/custom/" class="nav-link" aria-expanded="false">
                <i class="ti-palette"></i>Custom Page
            </a>
        </li>
    </ul>
</nav>

Multi-level - preferred

The problem happens when it comes to drop-down/sub-menu items...

My theme handles those like this...

enter image description here

<nav class="sidebar-nav">
  <ul id="sidebarnav">
      <li class="selected">
            <a class="has-arrow waves-effect waves-dark" href="javascript:void(0)" aria-expanded="false">
                <i class="icon-speedometer"></i>
                <span class="hide-menu">
                    Dashboard <span class="badge badge-pill badge-cyan">4</span>
                </span>
            </a>
            <ul aria-expanded="false" class="collapse">
              <li><a href="index.html">Minimal</a></li>
              <li><a href="index2.html">Analytical</a></li>
              <li><a href="index3.html">Demographical</a></li>
              <li class="active"><a href="index4.html" class="active">Modern</a></li>
              <li><a href="index5.html">Cryptocurrency</a></li>
          </ul>
      </li>
      <li>
          <a class="has-arrow waves-effect waves-dark" href="javascript:void(0)" aria-expanded="false">
                <i class="ti-layout-grid2"></i>
                <span class="hide-menu">Apps</span>
          </a>
          <ul aria-expanded="false" class="collapse">
              <li><a href="app-calendar.html">Calendar</a></li>
              <li><a href="app-chat.html">Chat app</a></li>
              <li><a href="app-ticket.html">Support Ticket</a></li>
              <li><a href="app-contact.html">Contact / Employee</a></li>
              <li><a href="app-contact2.html">Contact Grid</a></li>
              <li><a href="app-contact-detail.html">Contact Detail</a></li>
              <li><a href="javascript:void(0)" class="has-arrow">Inbox</a>
                  <ul aria-expanded="false" class="collapse">
                      <li><a href="app-email.html">Mailbox</a></li>
                      <li><a href="app-email-detail.html">Mailbox Detail</a></li>
                      <li><a href="app-compose.html">Compose Mail</a></li>
                  </ul>
              </li>
          </ul>
      </li>
    </nav>

... That is, it:

  • adds a <span> with .hide-menu inside the top-level link <a>
  • adds an <ul> unordered list afterward.

This is the approach I want to stick to.

Multi-level: what navwalker gives

However, when using the navwalker, I get...

enter image description here

<nav class="sidebar-nav">
    <ul id="sidebarnav" class="menu">
        <li id="menu-item-3" class="menu-item menu-item-type-custom menu-item-object-custom current-menu-item current_page_item menu-item-home menu-item-has-children menu-item-3 nav-item dropdown active">
            <a title="Home Page" target="_blank" href="http://sandbox.contexthq.com/" class="nav-link dropdown-toggle active" data-toggle="dropdown" aria-expanded="false">
                <i class="icon-speedometer"></i>Home Page</a>
                <div class="dropdown-menu">
                    <a href="http://sandbox.contexthq.com/sample-page/" class="dropdown-item" aria-expanded="false"><i class="ti-palette"></i>Sample Page</a>
                </div>
        </li>
        ...
    </ul>
</nav>

That is, it...

  • places a <div> with .dropdown-menu inside the <a>, instead of a <span> with .hide-menu
  • for the sub-menu items, uses <a> elements

I'm sure this is standard Bootstrap 4 behaviour - in fact, I have happily used it this way on a different site. However, it's not what is needed by the Bootstrap 4 theme which I have purchased and am currently trying to turn in to a WordPress theme...

The question

How can I use the bs4navwalker but in a way that will present drop-down/sub-menu items in a manner consistent with my theme... ?

0

STEP 1 add a script to header like below ( it's always better go for the enqueue method . i need some one to help me with properly adding the below script in WordPress way .jquery should run before the second script>

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js" type="text/javascript"></script>
<script>
$(document).ready(function () {
$('.dropdown-menu a.dropdown-toggle').on('click', function(e) {
  if (!$(this).next().hasClass('show')) {
    $(this).parents('.dropdown-menu').first().find('.show').removeClass("show");
  }
  var $subMenu = $(this).next(".dropdown-menu");
  $subMenu.toggleClass('show');


  $(this).parents('li.nav-item.dropdown.show').on('hidden.bs.dropdown', function(e) {
    $('.dropdown-submenu .show').removeClass("show");
  });


  return false;
});
});

</script>

STEP 2 Add the css like below :

.dropdown-submenu {
  position: relative;
}

.dropdown-submenu a::after {
  transform: rotate(-90deg);
  position: absolute;
  right: 6px;
  top: .8em;
}

.dropdown-submenu .dropdown-menu {
  top: 0;
  left: 100%;
  margin-left: .1rem;
  margin-right: .1rem;
}

STEP 3 Now go inside the walker class : search for && 0 === $depth and remove it. Also make sure that

'depth' => 3

Now it should start showing the 3rd level menu . some additional css might be required. Just let me know how it goes

1
  • Thanks for this. I hadn't thought of manipulating the page like that. But I was hopeful a solution would come from modifying the navwalker class, rather than this. Jul 23 '18 at 21:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.