Closed rianfloo closed 3 years ago
Hi @rianfloo!
I don't think this is possible without adjusting the walker. The walker walks the items you provided via the menu management. Is that what you are asking for? How to adjust the walker to achieve this?
Ian is correct, the walker doesn't allow this as it is built. You could look into the wp_nav_menu_items
filter and maybe make what you need happen https://developer.wordpress.org/reference/hooks/wp_nav_menu_items/
Thanks for your answer :) I would like to update the walker to add the following behaviour.
<ul class="dropdown-menu" role="menu">
<li><button class="go-back"> Go back (First item generated by updated walker with go back button)</button></li>
<li><a href="#" class="go-back">Menu item (classic menu item)</button></li>
</ul>
I will have a look to wp_nav_menu_items.
Thanks a lot :)
@rianfloo Put this inside the wp bootstrap walker class:
public function display_element( $element, &$children_elements, $max_depth, $depth, $args, &$output ) {
if ( 1 === (int) $element->menu_order ) {
$menu_item_title = __( 'Back to Home', 'theme_slug' );
$class_to_hide_on_desktop = 'class-to-hide-on-desktop';
$custom_element = new stdClass();
$custom_element->ID = 0;
$custom_element->post_title = $menu_item_title;
$custom_element->post_status = 'publish';
$custom_element->post_parent = 0;
$custom_element->menu_order = 0;
$custom_element->post_type = 'nav_menu_item';
$custom_element->filter = 'raw';
$custom_element->db_id = 0;
$custom_element->menu_item_parent = '0';
$custom_element->object_id = (string) get_option('page_on_front');
$custom_element->object = 'custom';
$custom_element->type = 'custom';
$custom_element->title = $menu_item_title;
$custom_element->url = get_home_url();
$custom_element->target = '';
$custom_element->attr_title = '';
$custom_element->description = '';
$custom_element->classes = array( $class_to_hide_on_desktop, 'menu-item', 'menu-item-type-custom', 'menu-item-object-custom' );
$custom_element->xfn = '';
$custom_element->current = false;
$custom_element->current_item_ancestor = false;
$custom_element->current_item_parent = false;
parent::display_element( $custom_element, $children_elements, $max_depth, $depth, $args, $output );
}
parent::display_element( $element, $children_elements, $max_depth, $depth, $args, $output );
}
This mimics a nav item. The if statement ( 1 === (int) $element->menu_order )
tells the walker to put the item in front of the first item. If you really want that item to be the first in each dropdown - for whatever reason - try this if statement instead if ( 1 == $depth )
.
I haven't tested this approach though.
The advantage over the approach suggest by @pattonwebz is that you don't have to care about the actual markup of the nav item but only about its content.
I just had a look at wp_nav_menu()
and found this hook: wp_get_nav_menu_items
. If I'm not mistaken, that's how it should work without adjusting the walker:
add_filter( 'wp_get_nav_menu_items', 'slug_add_go_back_menu_item' );
function slug_add_go_back_menu_item( $items ) {
$elements = array();
$found_parents = array();
$menu_order = 1;
foreach ( $items as $item ) {
$menu_item_parent = (int) $item->menu_item_parent;
$item->menu_order = $menu_order;
if ( 0 !== $menu_item_parent ) { // this is not a top-level item
if ( ! in_array( $menu_item_parent, $found_parents, true ) ) { // this is the first child of the parent
$custom_element = slug_get_go_back_menu_item( $menu_order, $menu_item_parent );
++$menu_order;
$item->menu_order = $menu_order;
$elements[] = $custom_element;
$found_parents[] = $menu_item_parent;
}
}
$elements[] = $item;
++$menu_order;
}
return $elements;
}
function slug_get_go_back_menu_item( $menu_order, $menu_item_parent ) {
$menu_item_title = __( 'Back to Home', 'theme_slug' );
$class_to_hide_on_desktop = 'class-to-hide-on-desktop';
$custom_element = new stdClass();
$custom_element->ID = 0;
$custom_element->post_title = $menu_item_title;
$custom_element->post_status = 'publish';
$custom_element->post_parent = 0;
$custom_element->menu_order = $menu_order;
$custom_element->post_type = 'nav_menu_item';
$custom_element->filter = 'raw';
$custom_element->db_id = 0;
$custom_element->menu_item_parent = $menu_item_parent;
$custom_element->object_id = (string) get_option('page_on_front');
$custom_element->object = 'custom';
$custom_element->type = 'custom';
$custom_element->title = $menu_item_title;
$custom_element->url = get_home_url();
$custom_element->target = '';
$custom_element->attr_title = '';
$custom_element->description = '';
$custom_element->classes = array( $class_to_hide_on_desktop, 'menu-item', 'menu-item-type-custom', 'menu-item-object-custom' );
$custom_element->xfn = '';
$custom_element->current = false;
$custom_element->current_item_ancestor = false;
$custom_element->current_item_parent = false;
return $custom_element;
}
@IanDelMar Thanks a lot! Better not adjusting the walker and simply use a function :)
You're welcome! I consider this solved.
Dear wp-boostrap-navwalker contributors,
I would like to add a an additional first items to all dropdown working as a go back button on mobile.
I found the solution to add a new item in the wordpress menu management and hide it on desktop but I would like to create it by using the navwalker class.
Any tips to do it?
Thanks a lot :)