# The last word on Sage 9 Bootstrap 4 Navwalkers

**URL:** https://discourse.roots.io/t/the-last-word-on-sage-9-bootstrap-4-navwalkers/11126
**Category:** sage
**Tags:** bootstrap4, navwalker, sage9
**Created:** 2017-12-13T02:33:36Z
**Posts:** 59

## Post 1 by @MWDelaney — 2017-12-13T02:33:37Z

Since the question of how to add a Bootstrap 4, Sage-friendly navwalker comes up a lot in this forum, I made a Sage composer dependency to solve the problem. Now, all you need to do is include this composer package in your Sage theme and the navwalker will be available to use.

Check it out:

> **[GitHub - MWDelaney/sage-bootstrap4-navwalker](https://github.com/MWDelaney/sage-bootstrap4-navwalker)**
>
> Contribute to MWDelaney/sage-bootstrap4-navwalker development by creating an account on GitHub.

From the README:

> Sets up a Bootstrap 4 Navwalker for Sage 9-based themes.
> 
> To install, run the following in your Sage9-based theme directory:
> 
> ```
> composer require "mwdelaney/sage-bootstrap4-navwalker"
> ```
> 
> Include the navwalker in your `wp_nav_menu` function:
> 
> ```
> wp_nav_menu( array(
> 'menu' => 'primary', 
> 'theme_location' => 'primary',
> ... 
> 'walker' => new wp_bootstrap4_navwalker())
> );
> ```

---

## Post 2 by @pi_mont — 2017-12-18T17:58:26Z

Dude, thank you so much for this.  
Having to manage/upgrade the old one was becoming a real pain.

**Edit:** Actually, I have run into an issue.  
After running composer require, when I attempt to use new wp\_bootstrap4\_navwalker()) as a walker, it gives me an error saying Class ‘wp\_bootstrap4\_navwalker’ not found.

Any idea what’s going on?

---

## Post 3 by @alwaysblank — 2017-12-18T18:43:42Z

Sounds like you’re probably not in the right namespace. It looks like `wp_bootstrap4_navwalker` is in the `App` namespace, so does the file you’re calling it from have `namespace App` up at the top? Can you show/tell us some more context about where you’re instantiating the `wp_bootstrap4_navwalker` class?

---

## Post 4 by @pi_mont — 2017-12-18T19:00:48Z

Bah, the lack of a namespace in my header.blade.php was it, thank you.

---

## Post 5 by @bonlando — 2018-02-16T18:55:08Z

I am getting the same error - sorry, can you elaborate on what you mean by adding the app name space?

Using the code given from the sage 9 docs

@if (has\_nav\_menu(‘primary\_navigation’))  
{!! wp\_nav\_menu([‘theme\_location’ =\> ‘primary\_navigation’, ‘menu\_class’ =\> ‘nav’, ‘walker’ =\> new wp\_bootstrap4\_navwalker())]) !!}  
@endif

---

## Post 6 by @MWDelaney — 2018-02-16T19:05:17Z

I actually just updated the README with more details on this. Here’s an excerpt:

Include the navwalker in your `wp_nav_menu` function:

## As a [Controller](https://github.com/soberwp/controller) method (Recommended)

In your Controller, probably `app.php`

```
/**
 * Primary Nav Menu arguments
 * @return array
 */
public function primarymenu() {
  $args = array(
    'theme_location' => 'primary_navigation',
    ...
    'walker' => new wp_bootstrap4_navwalker()
  );
  return $args;
}
```

In your Blade file, probably `header.blade.php`

```
@if (has_nav_menu('primary_navigation'))
  {!! wp_nav_menu($primarymenu) !!}
@endif
```

## Without Controller

If you’re not setting up your template data with Controller, you’ll need to fully reference the `\App\wp_bootstrap4_navwalker()`.  
In your Blade file, probably `header.blade.php`

```
@if (has_nav_menu('primary_navigation'))
  {!! wp_nav_menu(['theme_location' => 'primary_navigation', 'walker' => new \App\wp_bootstrap4_navwalker()]) !!}
@endif
```

---

## Post 7 by @patrice — 2018-04-12T08:18:23Z

That is a nice work, but it seems to be limited ton only 2 level for submenu. More than 2 level will not work without adding ‘depth’ =\> 2

---

## Post 8 by @Doocey — 2018-04-12T15:27:56Z

Bootstrap doesn’t support more than 1 submenu, out of the box.

---

## Post 9 by @peiche — 2018-04-18T15:19:53Z

Running `composer test` results in this error:

```
Fatal error: Class 'Walker_Nav_Menu' not found in ..\vendor\mwdelaney\sage-bootstrap4-navwalker\bootstrap4-navwalker.php on line 20
Script phpcs handling the test event returned with error code 255
```

Obviously the class exists within WordPress, but Composer doesn’t know about it. How can this error be fixed?

---

## Post 10 by @Davide_Prevosto — 2018-04-25T14:26:24Z

@peiche You need to run `composer require "mwdelaney/sage-bootstrap4-navwalker"` onto your “sage based” theme folder.

`eg. ./web/app/themes/my-theme``

It works for me

---

## Post 11 by @peiche — 2018-04-25T15:39:07Z

It still doesn’t work. You can run “composer test” without errors?

---

## Post 12 by @Davide_Prevosto — 2018-04-25T16:04:38Z

“composer test” returns your error.  
`PHP Fatal error: Class 'Walker_Nav_Menu' not found in /srv/www/blog.xxx.test/current/web/app/themes/xxx/vendor/mwdelaney/sage-bootstrap4-navwalker/bootstrap4-navwalker.php on line 20`

---

## Post 13 by @peiche — 2018-04-25T16:30:50Z

Yes, that’s what I’d like to resolve.

---

## Post 14 by @alwaysblank — 2018-04-25T16:40:45Z

It’s complaining because composer is running its tests with `phpcs` which is not able to load WordPress and therefor has no access to `Walker_Nav_Menu`. I don’t know what tests you’re running, but if those tests aren’t actually evaluating the output of the Bootstrap 4 nav walker, you might be able to prevent the error by just shiming in an empty object called `Walker_Nav_Menu`, i.e.

```
if (!class_exists('Walker_Nav_Menu')) {
    class \Walker_Nav_Menu {}
}
```

---

## Post 15 by @Simeon — 2018-05-14T04:53:59Z

+1 on this same error here, phpcs has drama with the class. Couldn’t work out where to put the above code to remove the error?

---

## Post 16 by @manus — 2018-05-21T13:25:01Z

Another one with the same error: “Fatal error: Class ‘Walker\_Nav\_Menu’ not found in …roots/vendor/mwdelaney/sage-bootstrap4-navwalker/bootstrap4-navwalker.php on line 20”

---

## Post 17 by @MWDelaney — 2018-05-21T15:55:06Z

Where and how is this error appearing?

---

## Post 18 by @ben — 2018-05-22T00:50:59Z

Run `composer test` from the theme directory with this package included :stuck_out_tongue:

---

## Post 19 by @manus — 2018-05-22T12:31:18Z

This is the result after running “composer test” from the theme directory:

> phpcs  
> PHP Fatal error: Class ‘Walker\_Nav\_Menu’ not found in /Applications/AMPPS/www/roots/web/app/themes/astro/vendor/mwdelaney/sage-bootstrap4-navwalker/bootstrap4-navwalker.php on line 20  
> PHP Stack trace:  
> PHP 1. {main}() /Applications/AMPPS/www/roots/web/app/themes/astro/vendor/squizlabs/php\_codesniffer/scripts/phpcs:0  
> PHP 2. include\_once() /Applications/AMPPS/www/roots/web/app/themes/astro/vendor/squizlabs/php\_codesniffer/scripts/phpcs:19  
> PHP 3. include\_once() /Applications/AMPPS/www/roots/web/app/themes/astro/vendor/squizlabs/php\_codesniffer/CodeSniffer/CLI.php:27  
> PHP 4. ComposerAutoloaderInit726026fe7d12aebd0d28444fd12d5cd0::getLoader() /Applications/AMPPS/www/roots/web/app/themes/astro/vendor/autoload.php:7  
> PHP 5. composerRequire726026fe7d12aebd0d28444fd12d5cd0() /Applications/AMPPS/www/roots/web/app/themes/astro/vendor/composer/autoload\_real.php:56  
> PHP 6. require() /Applications/AMPPS/www/roots/web/app/themes/astro/vendor/composer/autoload\_real.php:66

Fatal error: Class ‘Walker\_Nav\_Menu’ not found in /Applications/AMPPS/www/roots/web/app/themes/astro/vendor/mwdelaney/sage-bootstrap4-navwalker/bootstrap4-navwalker.php on line 20

Call Stack:  
0.0004 393048 1. {main}() /Applications/AMPPS/www/roots/web/app/themes/astro/vendor/squizlabs/php\_codesniffer/scripts/phpcs:0  
0.0062 583312 2. include\_once(‘/Applications/AMPPS/www/roots/web/app/themes/astro/vendor/squizlabs/php\_codesniffer/CodeSniffer/CLI.php’) /Applications/AMPPS/www/roots/web/app/themes/astro/vendor/squizlabs/php\_codesniffer/scripts/phpcs:19  
0.0373 585056 3. include\_once(‘/Applications/AMPPS/www/roots/web/app/themes/astro/vendor/autoload.php’) /Applications/AMPPS/www/roots/web/app/themes/astro/vendor/squizlabs/php\_codesniffer/CodeSniffer/CLI.php:27  
0.0385 599888 4. ComposerAutoloaderInit726026fe7d12aebd0d28444fd12d5cd0::getLoader() /Applications/AMPPS/www/roots/web/app/themes/astro/vendor/autoload.php:7  
0.1487 901600 5. composerRequire726026fe7d12aebd0d28444fd12d5cd0() /Applications/AMPPS/www/roots/web/app/themes/astro/vendor/composer/autoload\_real.php:56  
0.1868 936768 6. require(‘/Applications/AMPPS/www/roots/web/app/themes/astro/vendor/mwdelaney/sage-bootstrap4-navwalker/bootstrap4-navwalker.php’) /Applications/AMPPS/www/roots/web/app/themes/astro/vendor/composer/autoload\_real.php:66

Script phpcs handling the test event returned with error code 255

---

## Post 20 by @qbattersby — 2018-05-22T13:17:38Z

Just wanted to hop on here to say thanks for this. This makes adding the walker heaven.  
:hamburger:

---

## Post 21 by @MWDelaney — 2018-05-22T13:31:35Z

Can someone try replacing the contents of `[theme-directory]/vendor/mwdelaney/sage-bootstrap4-navwalker/bootstrap4-navwalker.php` with this:

```
<?php
namespace App;
/**
 * Bootstrap 4 "Navbar" component navwalker drop-in functionality for Sage 9
 * Version: 1.0
 * Author: Michael W. Delaney
 *
 */

/**
 * Class Name: wp_bootstrap4_navwalker
 * GitHub URI: https://github.com/twittem/wp-bootstrap-navwalker
 * Description: A custom WordPress nav walker class to implement the Bootstrap 3 navigation style in a custom theme using the WordPress built in menu manager.
 * Version: 2.0.4
 * Author: Edward McIntyre - @twittem
 * License: GPL-2.0+
 * License URI: http://www.gnu.org/licenses/gpl-2.0.txt
 */

if (class_exists('\Walker_Nav_Menu')) {

  class wp_bootstrap4_navwalker extends \Walker_Nav_Menu {
      /**
     * @see Walker::start_lvl()
     * @since 3.0.0
     *
     * @param string $output Passed by reference. Used to append additional content.
     * @param int $depth Depth of page. Used for padding.
     */
    public function start_lvl( &$output, $depth = 0, $args = array() ) {
      $indent = str_repeat( "\t", $depth );
      $output .= "\n$indent<div role=\"menu\" class=\" dropdown-menu\">\n";
    }
    /**
     * Ends the list of after the elements are added.
     *
     * @see Walker::end_lvl()
     *
     * @since 3.0.0
     *
     * @param string $output Passed by reference. Used to append additional content.
     * @param int $depth Depth of menu item. Used for padding.
     * @param array $args An array of arguments. @see wp_nav_menu()
     */
    public function end_lvl( &$output, $depth = 0, $args = array() ) {
      $indent = str_repeat("\t", $depth);
      $output .= "$indent</div>\n";
    }
    /**
     * Start the element output.
     *
     * @see Walker::start_el()
     *
     * @since 3.0.0
     *
     * @param string $output Passed by reference. Used to append additional content.
     * @param object $item Menu item data object.
     * @param int $depth Depth of menu item. Used for padding.
     * @param array $args An array of arguments. @see wp_nav_menu()
     * @param int $id Current item ID.
     */
    public function end_el( &$output, $item, $depth = 0, $args = array() ) {
      if($depth === 1){
        if(strcasecmp( $item->attr_title, 'divider' ) == 0 || strcasecmp( $item->title, 'divider') == 0) {
          $output .= '</div>';
        }else if ($depth === 1 && (strcasecmp( $item->attr_title, 'header') == 0 && $depth === 1)) {
          $output .= '</h6>';
        }
      }else{
        $output .= '</li>';
      }
    }
    /**
     * @see Walker::start_el()
     * @since 3.0.0
     *
     * @param string $output Passed by reference. Used to append additional content.
     * @param object $item Menu item data object.
     * @param int $depth Depth of menu item. Used for padding.
     * @param int $current_page Menu item ID.
     * @param object $args
     */
    public function start_el( &$output, $item, $depth = 0, $args = array(), $id = 0 ) {
      $indent = ( $depth ) ? str_repeat( "\t", $depth ) : '';
      /**
       * Dividers, Headers or Disabled
       * =============================
       * Determine whether the item is a Divider, Header, Disabled or regular
       * menu item. To prevent errors we use the strcasecmp() function to so a
       * comparison that is not case sensitive. The strcasecmp() function returns
       * a 0 if the strings are equal.
       */
      //( strcasecmp($item->attr_title, 'disabled' ) == 0 )

      if($depth === 1 && (strcasecmp( $item->attr_title, 'divider' ) == 0 || strcasecmp( $item->title, 'divider') == 0)) {
        $output .= $indent . '<div class="dropdown-divider">';
      }else if ((strcasecmp( $item->attr_title, 'header') == 0 && $depth === 1) && $depth === 1){
        $output .= $indent . '<h6 class="dropdown-header">' . esc_attr( $item->title );
      }else{
        $class_names = $value = '';
        $classes = empty( $item->classes ) ? array() : (array) $item->classes;

        $atts = array();
        $atts['title'] = ! empty( $item->title )	? $item->title	: '';
        $atts['target'] = ! empty( $item->target )	? $item->target	: '';
        $atts['rel'] = ! empty( $item->xfn ) ? $item->xfn	: '';
        $atts['href'] = ! empty( $item->url ) ? $item->url : '';
        $id = apply_filters( 'nav_menu_item_id', 'menu-item-'. $item->ID, $item, $args );

        if ( in_array( 'current-menu-item', $classes ) )
          $classes[] = ' active';
        if($depth === 0){
          $classes[] = 'nav-item';
          $classes[] = 'nav-item-' . $item->ID;
          $atts['class'] = 'nav-link';
          if ( $args->has_children ){
            $classes[] = ' dropdown';
            $atts['href'] = '#';
            $atts['data-toggle']	= 'dropdown';
            $atts['class'] = 'dropdown-toggle nav-link';
            $atts['role']	= 'button';
            $atts['aria-haspopup']	= 'true';
          }
          $class_names = join( ' ', apply_filters( 'nav_menu_css_class', array_filter( $classes ), $item, $args ) );
          $class_names = $class_names ? ' class="' . esc_attr( $class_names ) . '"' : '';
          $id = $id ? ' id="' . esc_attr( $id ) . '"' : '';
          $output .= $indent . '<li' . $id . $value . $class_names .'>';
        }else{
          $classes[] = 'dropdown-item';
          $class_names = join( ' ', apply_filters( 'nav_menu_css_class', array_filter( $classes ), $item, $args ) );
          $atts['class'] = $class_names;
          $atts['id'] = $id;
        }

        $atts = apply_filters( 'nav_menu_link_attributes', $atts, $item, $args );
        $attributes = '';
        foreach ( $atts as $attr => $value ) {
          if ( ! empty( $value ) ) {
            $value = ( 'href' === $attr ) ? esc_url( $value ) : esc_attr( $value );
            $attributes .= ' ' . $attr . '="' . $value . '"';
          }
        }
        $item_output = $args->before;
        $item_output .= '<a'. $attributes .'>';

        /*
        * Icons
        * ===========
        * Since the the menu item is NOT a Divider or Header we check the see
        * if there is a value in the attr_title property. If the attr_title
        * property is NOT null we apply it as the class name for the icon
        */
        if ( ! empty( $item->attr_title ) ){
          $item_output .= '<span class="' . esc_attr( $item->attr_title ) . '"></span>&nbsp;';
        }
        $item_output .= $args->link_before . apply_filters( 'the_title', $item->title, $item->ID ) . $args->link_after;
        $item_output .= '</a>';
        $item_output .= $args->after;
        $output .= apply_filters( 'walker_nav_menu_start_el', $item_output, $item, $depth, $args );
      }
    }
    /**
     * Traverse elements to create list from elements.
     *
     * Display one element if the element doesn't have any children otherwise,
     * display the element and its children. Will only traverse up to the max
     * depth and no ignore elements under that depth.
     *
     * This method shouldn't be called directly, use the walk() method instead.
     *
     * @see Walker::start_el()
     * @since 2.5.0
     *
     * @param object $element Data object
     * @param array $children_elements List of elements to continue traversing.
     * @param int $max_depth Max depth to traverse.
     * @param int $depth Depth of current element.
     * @param array $args
     * @param string $output Passed by reference. Used to append additional content.
     * @return null Null on failure with no changes to parameters.
     */
    public function display_element( $element, &$children_elements, $max_depth, $depth, $args, &$output ) {
      if ( ! $element )
        return;
      $id_field = $this->db_fields['id'];
      // Display this element.
      if ( is_object( $args[0] ) )
        $args[0]->has_children = ! empty( $children_elements[$element->$id_field] );
      parent::display_element( $element, $children_elements, $max_depth, $depth, $args, $output );
    }
    /**
     * Menu Fallback
     * =============
     * If this function is assigned to the wp_nav_menu's fallback_cb variable
     * and a manu has not been assigned to the theme location in the WordPress
     * menu manager the function with display nothing to a non-logged in user,
     * and will add a link to the WordPress menu manager if logged in as an admin.
     *
     * @param array $args passed from the wp_nav_menu function.
     *
     */
    public static function fallback( $args ) {
      if ( current_user_can( 'manage_options' ) ) {
        extract( $args );
        $fb_output = null;
        if ( $container ) {
          $fb_output = '<' . $container;
          if ( $container_id )
            $fb_output .= ' id="' . $container_id . '"';
          if ( $container_class )
            $fb_output .= ' class="' . $container_class . '"';
          $fb_output .= '>';
        }
        $fb_output .= '<ul';
        if ( $menu_id )
          $fb_output .= ' id="' . $menu_id . '"';
        if ( $menu_class )
          $fb_output .= ' class="' . $menu_class . '"';
        $fb_output .= '>';
        $fb_output .= '<li><a href="' . admin_url( 'nav-menus.php' ) . '">Add a menu</a></li>';
        $fb_output .= '</ul>';
        if ( $container )
          $fb_output .= '</' . $container . '>';
        echo $fb_output;
      }
    }
  }
}
```

And see if it fixes the issue and still works?

---

## Post 22 by @Lindsey_Rampton — 2018-05-23T02:58:48Z

Hey @MWDelaney that did help a bit - I did need to switch the namespace to:

```
namespace App\Controllers;
```

---

## Post 23 by @Jimmy_Turgeon_Trovac — 2018-05-23T19:09:05Z

Hi @MWDelaney, I get this error with your code that you asked to pasted (above):

`Fatal error: Uncaught Error: Class 'App\wp_bootstrap4_navwalker' not found in /srv/www/website.com/current/web/app/themes/website/app/controllers/app.php on line`

Before I got that the NavWalker wasn’t found. I used the method with the Controller, tried to add namespace in many ways, always get a error. I use Trellis Bedrock and Sage with Soil plugin.

Thank you

---

## Post 24 by @Jimmy_Turgeon_Trovac — 2018-05-23T20:59:27Z

Oh my mistake, seems to be fine,

I was running composer require from site/ (Bedrock), it must be run from theme folder as it was write in the readme, also it require `<?php namespace App; ?>` in the header.blade.php file

Thanks a lot for this

---

## Post 25 by @peiche — 2018-05-30T20:45:05Z

This fixes is for me when I run `composer test` manually, but my CI test fails because it pulls the class which does not have that `class_exists` line. Any chance that could get updated, please?

---

## Post 26 by @MWDelaney — 2018-05-30T21:30:17Z

I’m sorry I don’t understand. It “pulls the class” how? Do you mean that it installs it from Composer?

---

## Post 27 by @peiche — 2018-05-30T22:04:11Z

Yes. I can modify the existing class locally, but I don’t want to commit anything in /vendor. Can you update the class that gets downloaded from Composer?

---

## Post 28 by @MWDelaney — 2018-05-30T22:14:38Z

Absolutely. I just wanted to make sure the fix was good before committing. I’ll get it updated later tonight.

---

## Post 29 by @peiche — 2018-05-30T22:27:29Z

Awesome. Thanks so much!

---

## Post 30 by @MWDelaney — 2018-05-31T13:09:02Z

Hey,  
I just pushed a new release with the above fix in it. Should be all set. Let me know if you run into anymore trouble!

---

## Post 31 by @AmirFarid — 2018-06-07T16:35:06Z

Hello There,

Sorry if im being a bit thick here but ive spent ages getting a test site up with trellis and vagrant. everything is working now.

However as sage is a stripped down version i dont have a bootstap nav! so i have followed steps above and indeed its pulled the git repo into the vendor directory. I have included the markup in header-blade.php BUT its still showing an unstyled nav with no responsive nav being shown if i make the browser smaller.

Am i missing something here??? i have ran yarn build a few times. I assumed that the default bootstrap css gets included when you do yarn build…

Loved the old sage, go into lib add my ref to new nav include it in header and bobs your uncle. Sage 9 is a much steeper learning curve and i m pulling my hair out again :frowning:

Can any one shed any light please…

---

## Post 32 by @MWDelaney — 2018-06-07T17:24:19Z

Can you show us the code you’re using? It’s difficult to troubleshoot without seeing it.

---

## Post 33 by @AmirFarid — 2018-06-07T17:42:56Z

sure. here is what i have in my header-blade.php:

```
<header class="banner">
  <div class="container">
    <a class="brand" href="{{ home_url('/') }}">{{ get_bloginfo('name', 'display') }}</a>
    <nav class="nav-primary">
      @if (has_nav_menu('primary_navigation'))
  {!! wp_nav_menu(['theme_location' => 'primary_navigation', 'walker' => new \App\wp_bootstrap4_navwalker(),'container' => 'div',
	'container_class' => 'collapse navbar-collapse',
	'container_id' => 'primary-nav', 'menu_class' => 'nav navbar-nav']) !!}
@endif
    </nav>
  </div>
</header>
```

---

## Post 34 by @MWDelaney — 2018-06-07T19:41:01Z

Ah, I see the confusion.

This is a nav item walker only, it doesn’t produce the rest of the Bootstrap navbar HTML for you; you’ll need to add the necessary containers and classes around the markup produced by this walker.

Compare the output of your template to the example markup in Bootstrap’s documentation and add whichever parts you’re missing:

> **[Navbar](https://getbootstrap.com/docs/4.1/components/navbar/)**
>
> Documentation and examples for Bootstrap’s powerful, responsive navigation header, the navbar. Includes support for branding, navigation, and more, including support for our collapse plugin.

---

## Post 35 by @AmirFarid — 2018-06-08T14:32:59Z

@MWDelaney thanks for the link you sent. Delay in reply was due to me testing it out just in case i got it wrong…

Well i have double checked and i am fairly sure im doing it right!

So I have made sure that the code exists i.e. the markup in the html. I used it via the nav walker in header-blade.php as initially indicated. Here it is:

```
<header class="banner">
  <div class="container">
    <a class="brand" href="{{ home_url('/') }}">{{ get_bloginfo('name', 'display') }}</a>
    <nav class="nav-primary">
	<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
    <span class="navbar-toggler-icon"></span>
  </button>
      @if (has_nav_menu('primary_navigation'))
  {!! wp_nav_menu(['theme_location' => 'primary_navigation', 'walker' => new \App\wp_bootstrap4_navwalker(),'container' => 'div',
	'container_class' => 'collapse navbar-collapse',
	'container_id' => 'primary-nav', 'menu_class' => 'nav navbar-nav']) !!}
@endif
    </nav>
  </div>
</header>
```

You can see that i have specified the container id/class and it also includes the toggle button for responsive.

Her is what a screen shot looks like of the normal navbar with the above walker implemented:

 ![png%20bootstrap%20normal%20navbar](https://discourse.roots.io/uploads/default/original/2X/9/969de129d8fd5e891dab7b85691b075ddb89bf12.png)

and this is what it looks like if a make the browser smaller:

 ![png%20bootstrap%20responsive%20navbar](https://discourse.roots.io/uploads/default/original/2X/b/b9fa436eba6f1dd8a4ea62a6268623d775198edc.png)

as you can see no navbar is shown. The styling is not present. To confirm the output of the html on that page is:

```
<html lang="en-US"><head>
  <meta charset="utf-8">
  <meta http-equiv="x-ua-compatible" content="ie=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
  <title>example.com – Just another WordPress site</title>
<meta name="robots" content="noindex,follow">
<link rel="dns-prefetch" href="//fonts.googleapis.com">
<link rel="dns-prefetch" href="//code.jquery.com">
<link rel="stylesheet" href="//fonts.googleapis.com/css?family=Roboto:400,700|Ubuntu:400,700">
<link rel="stylesheet" href="/app/themes/Example/dist/styles/main.css">
<link rel="canonical" href="http://example.test/">
</head>
  <body class="home page app-data index-data singular-data page-data page-2-data page-sample-page-data front-page-data">
        <header class="banner">
  <div class="container">
    <a class="brand" href="http://example.test/">example.com</a>
    <nav class="nav-primary">
	<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
    <span class="navbar-toggler-icon"></span>
  </button>
        <ul id="menu-menu-1" class="nav navbar-nav"><li class="menu-item menu-item-type-custom menu-item-object-custom current-menu-item current_page_item menu-item-home active nav-item nav-item-5"><a title="Home" href="http://exmaple.test/" class="nav-link">Home</a></li><li class="menu-item menu-item-type-post_type menu-item-object-page menu-item-home current-menu-item page_item page-item-2 current_page_item active nav-item nav-item-6"><a title="Sample Page" href="http://example.test/" class="nav-link">Sample Page</a></li></ul>
    </nav>
  </div>
</header> <div class="wrap container" role="document">
      <div class="content">
        <main class="main">
                 <div class="page-header">
  <h1>Sample Page</h1>
</div>
    <p>This is an example page. It’s different from a blog post because it will stay in one place and will show up in your site navigation (in most themes). Most people start with an About page that introduces them to potential site visitors. It might say something like this:</p>
<blockquote><p>Hi there! I’m a bike messenger by day, aspiring actor by night, and this is my website. I live in Los Angeles, have a great dog named Jack, and I like piña coladas. (And gettin’ caught in the rain.)</p></blockquote>
<p>…or something like this:</p>
<blockquote><p>The XYZ Doohickey Company was founded in 1971, and has been providing quality doohickeys to the public ever since. Located in Gotham City, XYZ employs over 2,000 people and does all kinds of awesome things for the Gotham community.</p></blockquote>
<p>As a new WordPress user, you should go to <a href="http://example.test/wp/wp-admin/">your dashboard</a> to delete this page and create new pages for your content. Have fun!</p>

          </main>
              </div>
    </div>
        <footer class="content-info">
  <div class="container">
      </div>
</footer>
    <script src="https://code.jquery.com/jquery-1.12.4.min.js"></script>
<script>(window.jQuery && jQuery.noConflict()) || document.write('<script src="/wp/wp-includes/js/jquery/jquery.js"><\/script>')</script>
<script src="/app/themes/Example/dist/scripts/main.js"></script>
  

</body></html>
```

not sure what i am doing wrong here. I havent added any scss yet so its all the autoload scss that getting called. It looks correct i.e. main.css is populated with what looks like the bootstrap 4.1 code

really stumped. I assumed that it was just a case of getting the nav walker file via composer command and then adding the correct nav html and nav responsive html and the it should look and work like the example given in the bootstrap link you provided. Not the case :frowning:

---

## Post 36 by @AmirFarid — 2018-06-08T15:48:16Z

Aha, im getting somewhere now @MWDelaney didn’t help that i was testing during the night. After some rest and doing another project and then coming back to it i seem to have made some progress!

So i now understand your comment about including the html bootstrap markup. I was expecting the html markup to be injected via the code that added to the navwalker caller:

```
@if (has_nav_menu('primary_navigation'))
  {!! wp_nav_menu(['theme_location' => 'primary_navigation', 'walker' => new \App\wp_bootstrap4_navwalker(),'container' => 'div',
	'container_class' => 'collapse navbar-collapse',
	'container_id' => 'navbarSupportedContent primary-nav',
	'menu_class' => 'nav navbar-nav']) !!}
@endif
```

I can see now that was were i was going wrong. Can you confirm that me adding those additional lines actually don’t work (i used to do that with other wordpress navs and it works) doesn’t seem to be the case with latest sage version.

I have had to manually add in the html elements surrounding the navwalker call and it all works as expected now.

I also noticed that if i used your bootstrap navwalker then clean menus no longer work. The soil plugin doesn’t do anything to the menu. That’s a bummer. If i revert back to the original version (and as long as i use the manual html elements included) then its a clean menu with no junk. Is that a bug in your navwalker?

---

## Post 37 by @alwaysblank — 2018-06-08T18:39:16Z

> [@AmirFarid](#):
>
> I also noticed that if i used your bootstrap navwalker then clean menus no longer work. The soil plugin doesn’t do anything to the menu.

Soil “cleans up” the menu by using its own Walker. Since you’re using @MWDelaney’s Walker, Soil’s is never used. That’s not a bug. If you feel like his plugin can be improved, I’m sure he’d be happy to review a [pull request](https://github.com/MWDelaney/sage-bootstrap4-navwalker/pulls).

---

## Post 38 by @AmirFarid — 2018-06-09T11:21:28Z

ah, thats such a shame. its so nice and clean to have clean html. It would be nice if @MWDelaney could review this and get a clean nav walker working like the soil one. Sorry no idea on how to do a pull request at moment as i dont use github (yea major downside i know I should be using it!).

---

## Post 39 by @MWDelaney — 2018-06-09T16:09:15Z

That’s not a feature I’m planning to add at this point.

---

## Post 40 by @alwaysblank — 2018-06-09T16:21:44Z

> [@AmirFarid](#):
>
> Sorry no idea on how to do a pull request at moment as i dont use github (yea major downside i know I should be using it!).

No time like the present to learn! Git is an invaluable tool for development, and collaboration is the foundation of open software like Sage. Here’s a good guide to help you learn how pull requests work: [How To Create a Pull Request on GitHub | DigitalOcean](https://www.digitalocean.com/community/tutorials/how-to-create-a-pull-request-on-github)

---

## Post 41 by @AmirFarid — 2018-06-09T16:47:43Z

ah. such a shame. thank for letting me know. Perhaps it will get me to delve into it and have a go myself.

Thanks @alwaysblank yup will do. have been meaning too for ages. Just dont get the opportunity.

---

## Post 42 by @AmirFarid — 2018-06-14T13:18:11Z

so i was fiddling about trying to work out how to get bootsrap nav working with soil and found this:

> [@How to restore the Bootstrap nav [walkthrough]](https://discourse.roots.io/t/how-to-restore-the-bootstrap-nav-walkthrough/3657/50):
>
> I recently put this together and have been meaning to share it here. It’s based on Soils clean nav and Michael Romero’s Sageextras plugin. Basic output looks like: - ul id="menu-main" class="navbar-nav mr-auto" - li class="nav-item menu-item menu-page-1" - a class="nav-link" It also supports drop downs. Setup should be pretty self explanatory, but I’m going to update my original post, or make a new one, this weekend. In the mean-time, header markup and instructions are in the full gi…

I actually commented on that post but must have missed it somehow. Anyways i used that custom nav walker and bootsrap nav works with clean menu links :slight_smile:

---

## Post 43 by @bonlando — 2018-09-10T21:27:17Z

I’m wondering if this is the right place to ask this, but the active class is not being added to any menu items that are linked to a custom post type. Any clue why that is?

---

## Post 44 by @daniel — 2018-12-10T14:36:30Z

@MWDelaney Thanks for this – Works great! What is the best way to make the parent-level menu items as active links without worrying about this being over written during an upgrade to your script? We found this: [https://medium.com/@oscarmwana/make-parent-link-clickable-in-bootstrap-wordpress-navigation-walker-61213063a1a0](https://medium.com/@oscarmwana/make-parent-link-clickable-in-bootstrap-wordpress-navigation-walker-61213063a1a0) - But it looks like this got overwritten at some point when one of our developers cloned the project.

Thanks in advance!

---

## Post 45 by @MWDelaney — 2018-12-10T14:38:44Z

Hi, @Daniel. Truly the best way to do this would be to fork the project and maintain that functionality yourself. Since top-level linking is not supported by Bootstrap, it’s not a priority in this project, and is likely to break (as you’ve found) when changes are made.

---

## Post 46 by @daniel — 2018-12-10T14:40:43Z

@MWDelaney Thank you sir!

---

## Post 48 by @Frykky — 2019-01-02T16:48:59Z

@AmirFarid have you resolved?

Is there a way to use bootstrap 4 nawalkers and soil?

---

## Post 49 by @gishua — 2019-02-06T20:39:06Z

> [@MWDelaney](#):
>
> /\*\* \* Primary Nav Menu arguments \* @return array \*/ public function primarymenu() { $args = array( ‘theme\_location’ =\> ‘primary\_navigation’, … ‘walker’ =\> new wp\_bootstrap4\_navwalker() ); return $args; }

Hi there,  
Thank you again for this! I can’t seem to get this to work out of the box. I have tried the controller way and adding namespace to the top as well, but to no avail. Any help would be appreciated.

**Fatal error** : Uncaught Error: Class ‘App\Controllers\wp\_bootstrap4\_navwalker’ not found in /www/sites/sage/wwwroot/wp-content/themes/mysage/app/Controllers/App.php:39

Thank you in advance,  
Josh

---

## Post 50 by @MWDelaney — 2019-02-06T20:59:48Z

The info in this thread is a little out of date. Be sure to check the documentation at the repository here:

> **[MWDelaney/sage-bootstrap4-navwalker](https://github.com/MWDelaney/sage-bootstrap4-navwalker)**
>
> Contribute to MWDelaney/sage-bootstrap4-navwalker development by creating an account on GitHub.

It looks like you need to change your `walker` from

```
...
    'walker' => new wp_bootstrap4_navwalker()
...
```

to

```
...
    'walker' => new \App\wp_bootstrap4_navwalker()
...
```

---

## Post 52 by @gishua — 2019-02-06T21:22:18Z

Thank you!!! This worked. Apologies.

---

## Post 53 by @boothwise — 2019-03-07T23:28:05Z

> Is there a way to use bootstrap 4 nawalkers and soil?

@MWDelaney , has there been any additional thought toward this, or is there another method to do this? I would be grateful.

I’ve been trying to figure this out for a week to work with Soil, but no luck… _Rookie_

---

## Post 54 by @MWDelaney — 2019-03-08T00:29:35Z

Soil’s navwalker and this one are alternative tools. They’re not meant to work together and I don’t plan to add they as a feature at this time.

---

## Post 55 by @boothwise — 2019-03-08T01:11:20Z

Thank you for the reply, I really do appreciate your knowledge…

Can you recommend a way to still use Soil with the nice links, but not have a lengthy class **“menu-item menu-item-type-post\_type menu-item-object-page nav-item nav-item-18”** utilizing this method?

Any help would be greatly appreciated – I have about 30+ links total and could definitely appreciate less bloat.

---

## Post 56 by @mmirus — 2019-03-08T15:50:22Z

Hey @boothwise - you probably need to create your own custom nav walker that combines the elements you want from each. Spending some time looking at the source of Michael’s BS nav walker and the soil nav walker will help you understand how they work and should give you all the insight you need.

---

## Post 57 by @Jan-Klaas — 2021-06-02T04:29:37Z

Does this still work with bootstrap 5?

---

## Post 58 by @mattegg — 2021-06-18T22:26:18Z

This is how I ended up doing it : [https://thewpgeek.com/add-a-responsive-menu-in-sage/](https://thewpgeek.com/add-a-responsive-menu-in-sage/) I would be interested in anything I should change in the tutorial (especially if something is not best practice)

---

## Post 59 by @aitor — 2021-06-21T05:43:41Z

> **[Log1x/navi](https://github.com/Log1x/navi)**
>
> A developer-friendly alternative to the WordPress NavWalker. - Log1x/navi
