Hot answers tagged

39

Since WordPress 3.0, you don't need a custom walker anymore! There is the walker_nav_menu_start_el filter, see https://developer.wordpress.org/reference/hooks/walker_nav_menu_start_el/ Example: function add_description_to_menu($item_output, $item, $depth, $args) { if (strlen($item->description) > 0 ) { // append description after link $...


15

It means that the declaration of the start_lvl method in wp_bootstrap_navwalker should match the declaration of the method in Walker_Nav_Menu. It doesn't. function start_lvl( &$output, $depth ) { VS. function start_lvl( &$output, $depth = 0, $args = array() ) { Make the arguments match exactly and you should be fine. And you should probably not ...


12

I searched and read about the walker class. I ran tests, I played around with the code and I finally understood. I hope this can be helpful to others too. You'll need to implement the walker class for this. Here is a simple example. $defaults = array( 'theme_location' => 'primary', 'container' => 'ul', 'menu_class' ...


10

You should be extending Walker_Category not the main Walker class. class Walker_Simple_Example extends Walker_Category { function start_lvl(&$output, $depth=1, $args=array()) { $output .= "\n<ul class=\"product_cats\">\n"; } function end_lvl(&$output, $depth=0, $args=array()) { $output .= "</ul>\n";...


10

There even is a way to make this possible with CSS alone. This has some limitations, but I still thought it might be an interesting approach: Limitations You need to hardcode the width of the dropdown Browser-Support. You basically need CSS3 selectors. But everything from IE8 up should work, although I haven't tested this. This is more of a proof-of-...


9

Using a custom Walker, the start_el() method has access to $depth param: when it is 0 the elemnt is a top one, and we can use this info to maintain an internal counter. When the counter reach a limit, we can use DOMDocument to get from full HTML output just the last element added, wrap it in a submenu and add it again to HTML. Edit When the number of ...


8

Your my_extended_walker class is OK, but when you call the wp_nav_menu function use the items_wrap parameter. wp_nav_menu( array( 'items_wrap' => '<p>%3$s</p>', 'walker'=>new my_extended_walker() ) ); The start_lvl is used for children elements.


8

If I understand correctly, you want links with submenus to have an attribute of aria-haspopup. If this is correct, you should be able to do so using the nav_menu_link_attributes filter (WP 3.6 and above). You can also get around the necessity of having to write a custom Walker to check if an item has children by checking its css classes in the filter. ...


8

Try adding this in your functions.php file: // Let's stop WordPress re-ordering my categories/taxonomies when I select them function stop_reordering_my_categories($args) { $args['checked_ontop'] = false; return $args; } // Let's initiate it by hooking into the Terms Checklist arguments with our function above add_filter('wp_terms_checklist_args'...


8

You can use wp_nav_menu_items filter. It accepts menu output and arguments which hold menu attributes, like menu slug, container, etc. add_filter('wp_nav_menu_items', 'wpse_180221_nav_menu_items', 20, 2); function wpse_180221_nav_menu_items($items, $args) { if ($args->menu != 'my-menu-slug') { return $items; } // extract all <li&...


8

You need to set-up your own menu walker (link to Wordpress Codex), and in there add custom start_el and end_el overrides. So for example your start_el and end_el may look something like this: function start_el(&$output, $item, $depth=0, $args=array()) { $output .= "<div>" . esc_attr($item->label); } function end_el(&$output, $item, $...


7

You could create a very simple walker, like this one. To detect the current item, inspect $item->current. It is TRUE for the current item only. I wouldn’t add a class, but deactivate the useless link completely, because it doesn’t have to be clickable anyway. Example: class One_Line_Walker extends Walker { public function walk( $elements, $...


7

If I understand the problem setup correctly, you could try to do the break and widget class counting within the wp_nav_menu_objects filter. Here's an updated example, it's rather expanded because of the extra debug part: add_filter( 'wp_nav_menu_objects', function( $items, $args ) { // Only apply this for the 'primary' menu: if( ...


6

You just need to create your own walker class and extend start_el method. This method builds a link and you will be able to add your span before it: class Wpse8170_Menu_Walker extends Walker_Nav_Menu { var $number = 1; function start_el( &$output, $item, $depth = 0, $args = array(), $id = 0 ) { $indent = ( $depth ) ? str_repeat( "\t", $...


6

This is the walker I used to display only children of the current menu item. Or the menu items siblings if it doesn't have any children of its own. There are comments throughout the class explaining each section <?php class SH_Child_Only_Walker extends Walker_Nav_Menu { private $ID; private $depth; private $classes = array(); private $child_count = 0; ...


6

To be honest, I don't really know why my solution works, but it does 😂 I based my snippet on this solution and tweaked the output to my needs: Custom nav walker with different output depending on depth class sublevel_wrapper extends Walker_Nav_Menu { // add classes to ul sub-menus function start_lvl( &$output, $depth = 0, $args = array() ) { ...


5

Expanding on @Eugene's answer, if you want to limit this to a specific menu, just check the term ID of the menu: function custom_nav_args($args){ $menu = $args['menu']; if($menu->term_id === 17) /* replace term_id with menu id, or use $menu->name to do it by menu name*/ { $args['walker'] = new My_Custom_Walker(); } return $...


5

You could try to use the wp_nav_menu_args filter (untested): /** * Add the Menu_With_Data_Attr walker to the wp_nav_menu() used by genesis_do_nav() */ add_filter( 'wp_nav_menu_args', function( $args ){ if( isset( $args['menu_class'] ) && 'menu genesis-nav-menu menu-primary' === $args['menu_class'] ) { if( class_exists(...


5

Got a working function, but not sure if it is the best solution. I used a custom walker: class Custom_Walker_Nav_Menu extends Walker_Nav_Menu { function start_el( &$output, $item, $depth = 0, $args = array(), $id = 0 ) { global $wp_query; $indent = ( $depth ) ? str_repeat( "\t", $depth ) : ''; $classes = empty( $item->classes ) ? array(...


5

We can add custom nav menu classes through the nav_menu_css_class filter. Example: The following should add the CSS class wpse-object-id-{object_id} to the <li> tags: // Add filter add_filter( 'nav_menu_css_class', 'wpse_menu_item_id_class', 10, 2 ); // Your navigational menu wp_nav_menu( $args ); // Remove filter remove_filter( '...


5

Your menu doesn't appear to have any levels. start_lvl and end_lvl are used for the sub-menu wrappers. The outer wrapper for the menu, the <ul> is defined by the items_wrap argument of wp_nav_menu(): wp_nav_menu( [ 'walker' => new My_Walker(), 'items_wrap' => '<nav id="%1$s" class="%2$s">%3$s</nav>', ] );


4

You need to do something with the function end_el. I made a custom walker to generate a select menu and I didn't get clean output until I overwrote end_el and generated the closing option tag in there. Trying to do it all in start_el() was causing headaches. Try removing the closing div from this line . '</a></div>' and change it to only close ...


4

I just resolved this issue! Woo hoo! The thing is that using var_dump($args) shows a lot stuff like so: object(stdClass)#152 (16) { ["menu"]=> object(WP_Term)#145 (10) { ["term_id"]=> int(2) ["name"]=> string(9) "Main menu" ["slug"]=> string(9) "main-menu" ["term_group"]=> int(0) ["term_taxonomy_id"]=> int(2) ["taxonomy"]=> string(8) "...


4

Not sure, but maybe something like this will work? Add to the functions.php. See explanation here. //This function is responsible for adding "my-parent-item" class to parent menu item's function add_menu_parent_class( $items ) { $parents = array(); foreach ( $items as $item ) { //Check if the item is a parent item if ( $item->menu_item_parent &...


4

We could rewrite: wp_list_comments( array( 'callback' => 'bootstrap_comment_callback', )); with the null walker parameter: wp_list_comments( array( 'walker' => null, 'callback' => 'bootstrap_comment_callback', )); which means we are using the default Walker_Comment class: wp_list_comments( array( 'walker' ...


4

As @toscho said, you can call the walker class with parameters as you did: new BEMwalker( 'mobile' ) The constructor of BEMwalker will take the arguments (like any other function or method in PHP) so you can access the parameter(s) via $this: class BEMwalker extends Walker_Nav_Menu { private $classes; public function __construct( $classes = '' ) ...


4

Walker_Nav_Menu isn't what you would use for this. Instead, use the wp_get_nav_menu_items filter. Before we start, you need some way of allowing the code to identify which is the menu item/page that you wish to be the parent of the list of posts. You can do this with a CSS class - give the parent menu item a CSS class in admin panel, let's call it 'doctors-...


4

I believe wp_nav_menu() handles the top-level list wrapping so start_lvl method would only handle submenu items ( from my understanding ). It also doesn't give us access to the $item which we need to get the parent. Below I've setup a boolean variable to track whether we should be showing our title or not. It also keeps it HTML valid, lists can only contain ...


4

Apparently custom nav menu walkers are not supported though they were supposed to be. I'm surprised this only has been discovered now. However, there is an easy fix for you to get them to work. Just add this to your theme: add_filter( 'wp_nav_menu_args', function( $args ) { if ( isset( $args['walker'] ) && is_string( $args['walker'] ) && ...


3

At first glance, and without testing anything, the code you've got should work but I expect that you have a number of spurious </ul> in your markup. You need to do nearly the same thing for the end_lvl method. function end_lvl(&$output, $depth) { if($depth >= 2) { $output .= ''; } else { $output .= "</ul>"; } ...


Only top voted, non community-wiki answers of a minimum length are eligible