Roots Discourse

How to add a new UiKit Walker?

Hi,

I am new here and using Local by Flywheel to try out Bedrock, Sage 9, and Soil plugin (installed and activated) using UIKit CSS framework.

Everything is good until I got stuck in the menu section, basically having difficulty adding a new UIKit Walker.

Below are the two files of my current progress:

  1. header.blade.php inside partials folder

     <header class="banner">
       <div class="uk-container uk-container-expand">
         <nav class="uk-navbar-container" uk-navbar>
           <div class="uk-navbar-left">
             <!-- <a class="brand" href="{{ home_url('/') }}">{{ get_bloginfo('name', 'display') }}</a>-->
             <a class="uk-navbar-item uk-logo" href="#"><img src="@asset('images/nomis-blue-logo.png')"></a>
           </div>
           <div class="uk-navbar-right">
           @if (has_nav_menu('primary_navigation'))
             {!! wp_nav_menu([
                 'theme_location' => 'primary_navigation', 
                 'menu_class' => 'uk-navbar-nav uk-visible@m',  
                 'walker' => new App\Controllers\UIKit_Walker ]) !!}
           @endif
           </div>
         </nav>
       </div>
     </header>
    
  2. UIKit_Walker.php inside of app/Controllers folder

     <?php
    
     namespace App\Controllers;
    
     /* Add UIkit classes to menu*/
     class UIKit_Walker extends Walker_Nav_Menu
     {
         // add classes to ul sub-menus
     function start_lvl( &$output, $depth = 0, $args = array() ) {
         // depth dependent classes
         $indent = ( $depth > 0  ? str_repeat( "\t", $depth ) : '' ); // code indent
         $display_depth = ( $depth + 1); // because it counts the first submenu as 0
         $classes = array(
             'sub-menu',
             ( $display_depth % 2  ? 'menu-odd' : 'menu-even' ),
             ( $display_depth >=2 ? 'sub-sub-menu' : '' ),
             'menu-depth-' . $display_depth
             );
         $class_names = implode( ' ', $classes );
    
         // build html
         if( $depth == 0 ) $output .= "\n" . $indent . '<div class="uk-navbar-dropdown" uk-drop="boundary: .uk-navbar; boundary-align: true; align: right; pos: bottom-justify; offset: 0;delay-hide:100"><ul class="uk-nav uk-navbar-dropdown-nav uk-grid-medium uk-grid uk-child-width-expand" >' . "\n";
     	
    
     	if( $depth > 0 ) $output .= "\n" . $indent . '<div><ul class="uk-nav uk-navbar-dropdown-nav">' . "\n";
    
     }
      function end_lvl(&$output, $depth=0, $args=array()) {
            $output .= "</ul></div>\n";
    
         }
    
     // add main/sub classes to li's and links
      function start_el(  &$output, $item, $depth = 0, $args = array(), $id = 0 ) {
         global $wp_query;
         $indent = ( $depth > 0 ? str_repeat( "\t", $depth ) : '' ); // code indent
    
         // depth dependent classes
         $depth_classes = array(
             ( $depth == 0 ? 'main-menu-item' : 'sub-menu-item' ),
             ( $depth >=2 ? 'uk-nav-cat-sub' : '' ),
             ( $depth % 2 ? 'menu-item-odd' : 'menu-item-even' ),
             'menu-item-depth-' . $depth
         );
         $depth_class_names = esc_attr( implode( ' ', $depth_classes ) );
    
         // passed classes
         $classes = empty( $item->classes ) ? array() : (array) $item->classes;
         $class_names = esc_attr( implode( ' ', apply_filters( 'nav_menu_css_class', array_filter( $classes ), $item ) ) );
    
         // build html
         $output .= $indent . '<li class="' . $depth_class_names . '">';
    
         // link attributes
         $attributes  = ! empty( $item->attr_title ) ? ' title="'  . esc_attr( $item->attr_title ) .'"' : '';
         $attributes .= ! empty( $item->target )     ? ' target="' . esc_attr( $item->target     ) .'"' : '';
         $attributes .= ! empty( $item->xfn )        ? ' rel="'    . esc_attr( $item->xfn        ) .'"' : '';
         $attributes .= ! empty( $item->url )        ? ' href="'   . esc_attr( $item->url        ) .'"' : '';
         $attributes .= ' class=""';
         
         $description .= ! empty($item->description) ? '<span class="uk-text-small uk-menu-description">' . esc_attr( $item->description ) . '</span>' : '';
    
         $format = '%1$s<a%2$s><div>%3$s%4$s%5$s</div></a>%6$s';
     if( $depth == 1 ) $format = '%1$s<a%2$s><div class="uk-nav-cat-header">%3$s%4$s%5$s</div></a>%6$s';
     $item_output = sprintf( $format,
             $args->before,
             $attributes,
             $args->link_before,
             apply_filters( 'the_title', $item->title, $item->ID ),
     	$description,
             $args->link_after,
             $args->after
         );
    
         // build html
         $output .= apply_filters( 'walker_nav_menu_start_el', $item_output, $item, $depth, $args );
     }
     }
    

In my previous non-Sage Wordpress project, I would place the class UIKit_Walker extends Walker_Nav_Menu in functions.php and it will work.

However, in Sage theme, below is the error that i am getting:

Please advise. Thanks!

This can be caused by case-sensitivity in the file system. The loader expects app, but the class starts with App, renaming the folder to App fixes your issue?

I tried that but it is still giving me similar error.

I found this tutorial from: [https://www.freshconsulting.com/insights/blog/modernizing-wordpress-development-sage-9-part-1/](http://Modernizing WordPress Development with Sage 9 – Part 1)

Based on that tutorial I moved the Uikit_Walker into .app/classes/Uikit_Walker.class.php

<?php

namespace App\Classes;

/* Add Uikit classes to menu*/

class Uikit_Walker extends Walker_Nav_Menu

{

    // add classes to ul sub-menus

function start_lvl( &$output, $depth = 0, $args = array() ) {

    // depth dependent classes

    $indent = ( $depth > 0  ? str_repeat( "\t", $depth ) : '' ); // code indent

    $display_depth = ( $depth + 1); // because it counts the first submenu as 0

    $classes = array(

        'sub-menu',

        ( $display_depth % 2  ? 'menu-odd' : 'menu-even' ),

        ( $display_depth >=2 ? 'sub-sub-menu' : '' ),

        'menu-depth-' . $display_depth

        );

    $class_names = implode( ' ', $classes );

    // build html

    if( $depth == 0 ) $output .= "\n" . $indent . '<div class="uk-navbar-dropdown" uk-drop="boundary: .uk-navbar; boundary-align: true; align: right; pos: bottom-justify; offset: 0;delay-hide:100"><ul class="uk-nav uk-navbar-dropdown-nav uk-grid-medium uk-grid uk-child-width-expand" >' . "\n";

    

    if( $depth > 0 ) $output .= "\n" . $indent . '<div><ul class="uk-nav uk-navbar-dropdown-nav">' . "\n";

    }

function end_lvl(&$output, $depth=0, $args=array()) {

       $output .= "</ul></div>\n";

    }

// add main/sub classes to li's and links

function start_el(  &$output, $item, $depth = 0, $args = array(), $id = 0 ) {

    global $wp_query;

    $indent = ( $depth > 0 ? str_repeat( "\t", $depth ) : '' ); // code indent

    // depth dependent classes

    $depth_classes = array(

        ( $depth == 0 ? 'main-menu-item' : 'sub-menu-item' ),

        ( $depth >=2 ? 'uk-nav-cat-sub' : '' ),

        ( $depth % 2 ? 'menu-item-odd' : 'menu-item-even' ),

        'menu-item-depth-' . $depth

    );

    $depth_class_names = esc_attr( implode( ' ', $depth_classes ) );

    // passed classes

    $classes = empty( $item->classes ) ? array() : (array) $item->classes;

    $class_names = esc_attr( implode( ' ', apply_filters( 'nav_menu_css_class', array_filter( $classes ), $item ) ) );

    // build html

    $output .= $indent . '<li class="' . $depth_class_names . '">';

    // link attributes

    $attributes  = ! empty( $item->attr_title ) ? ' title="'  . esc_attr( $item->attr_title ) .'"' : '';

    $attributes .= ! empty( $item->target )     ? ' target="' . esc_attr( $item->target     ) .'"' : '';

    $attributes .= ! empty( $item->xfn )        ? ' rel="'    . esc_attr( $item->xfn        ) .'"' : '';

    $attributes .= ! empty( $item->url )        ? ' href="'   . esc_attr( $item->url        ) .'"' : '';

    $attributes .= ' class=""';

    

    $description .= ! empty($item->description) ? '<span class="uk-text-small uk-menu-description">' . esc_attr( $item->description ) . '</span>' : '';

    $format = '%1$s<a%2$s><div>%3$s%4$s%5$s</div></a>%6$s';

    if( $depth == 1 ) $format = '%1$s<a%2$s><div class="uk-nav-cat-header">%3$s%4$s%5$s</div></a>%6$s';

    $item_output = sprintf( $format,

        $args->before,

        $attributes,

        $args->link_before,

        apply_filters( 'the_title', $item->title, $item->ID ),

    $description,

        $args->link_after,

        $args->after

    );

    // build html

    $output .= apply_filters( 'walker_nav_menu_start_el', $item_output, $item, $depth, $args );

    }

}

Then I changed the header.blade.php to this (including changing App to lower case):

<header class="banner">

  <div class="uk-container uk-container-expand">

    <nav class="uk-navbar-container" uk-navbar>

      <div class="uk-navbar-left">

        <!-- <a class="brand" href="{{ home_url('/') }}">{{ get_bloginfo('name', 'display') }}</a>-->

        <a class="uk-navbar-item uk-logo" href="#"><img src="@asset('images/nomis-blue-logo.png')"></a>

      </div>

      <div class="uk-navbar-right">

      @if (has_nav_menu('primary_navigation'))

        {!! wp_nav_menu([

        'theme_location' => 'primary_navigation', 

        'menu_class' => 'uk-navbar-nav uk-visible@m', 

        'walker' => new app\classes\Uikit_Walker ]) !!}

      @endif

      </div>

    </nav>

  </div>

</header>

And now this is the error I am getting:

I recommend you read our article on namespacing: https://roots.io/namespacing-and-autoloading/

If you read your error, it says it can’t find App\Classes\Walker_Nav_Menu. The Walker_Nav_Menu class is a core WordPress class, and does not have a namespace, so why does it have one here? Because of the namespace you added to your file:

namespace App\Classes;

That means that when you write

class Uikit_Walker extends Walker_Nav_Menu

It resolves to the following:

class App\Classes\Uikit_Walker extends App\Classes\Walker_Nav_Menu

… and App\Classes\Walker_Nav_Menu doesn’t exist.

You can solve this by making sure you refer to Walker_Nav_Menu from the root namespace:

class Uikit_Walker extends \Walker_Nav_Menu

Thank you! Yes, I wasn’t super clear on that namespace concept.

I have updated the code and my Uikit menu shows up properly now. Below is a screenshot for others who may need it.

And this is the header.blade.php

BTW I noticed that my image wasn’t showing up either when there is a dash in the file name. So I also changed that from image-file-name.png to filename.png then it renders correctly.

This topic was automatically closed after 42 days. New replies are no longer allowed.