Bootstrap 4 navwalker - multilevel menu - php

I'm using this nav walker in my Wordpress project. I want to create multilevel menu, for example. What I need to change to get it work? Or maybe is it another walker for BS4 with multilevel menu support?
Menu Item
- Sub menu
-- Sub menu item
-- Sub menu item
Menu Item

Add this css
ul.dropdown-menu li > ul.dropdown-menu{
left: 100%;
top: 0;
}
ul.dropdown-menu li:hover > ul.dropdown-menu, ul.dropdown-menu li:focus > ul.dropdown-menu{
display: block
}
Remove this code && 0 === $depth from class-wp-bootstrap-navwalker.php
original code:
if ( isset( $args->has_children ) && $args->has_children && 0 === $depth && $args->depth > 1 ) {
After editing:
if ( isset( $args->has_children ) && $args->has_children && $args->depth > 1 ) {

Bulding simple menu list - here in user contributed notes (1st one) you can find code for build menu using menu array data, its simple and can be modified as you need.
Here is the code:
<?php
// Intented to use bootstrap 3.
// Location is like a 'primary'
// After, you print menu just add create_bootstrap_menu("primary") in your
preferred position;
#add this function in your theme functions.php
function create_bootstrap_menu( $theme_location ) {
if ( ($theme_location) && ($locations = get_nav_menu_locations()) && isset($locations[$theme_location]) ) {
$menu_list = '<nav class="navbar navbar-default">' ."\n";
$menu_list .= '<div class="container-fluid">' ."\n";
$menu_list .= '<!-- Brand and toggle get grouped for better mobile display -->' ."\n";
$menu_list .= '<div class="navbar-header">' ."\n";
$menu_list .= '<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false">' ."\n";
$menu_list .= '<span class="sr-only">Toggle navigation</span>' ."\n";
$menu_list .= '<span class="icon-bar"></span>' ."\n";
$menu_list .= '<span class="icon-bar"></span>' ."\n";
$menu_list .= '<span class="icon-bar"></span>' ."\n";
$menu_list .= '</button>' ."\n";
$menu_list .= '<a class="navbar-brand" href="' . home_url() . '">' . get_bloginfo( 'name' ) . '</a>';
$menu_list .= '</div>' ."\n";
$menu_list .= '<!-- Collect the nav links, forms, and other content for toggling -->';
$menu = get_term( $locations[$theme_location], 'nav_menu' );
$menu_items = wp_get_nav_menu_items($menu->term_id);
$menu_list .= '<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">' ."\n";
$menu_list .= '<ul class="nav navbar-nav">' ."\n";
foreach( $menu_items as $menu_item ) {
if( $menu_item->menu_item_parent == 0 ) {
$parent = $menu_item->ID;
$menu_array = array();
foreach( $menu_items as $submenu ) {
if( $submenu->menu_item_parent == $parent ) {
$bool = true;
$menu_array[] = '<li>' . $submenu->title . '</li>' ."\n";
}
}
if( $bool == true && count( $menu_array ) > 0 ) {
$menu_list .= '<li class="dropdown">' ."\n";
$menu_list .= '' . $menu_item->title . ' <span class="caret"></span>' ."\n";
$menu_list .= '<ul class="dropdown-menu">' ."\n";
$menu_list .= implode( "\n", $menu_array );
$menu_list .= '</ul>' ."\n";
} else {
$menu_list .= '<li>' ."\n";
$menu_list .= '' . $menu_item->title . '' ."\n";
}
}
// end <li>
$menu_list .= '</li>' ."\n";
}
$menu_list .= '</ul>' ."\n";
$menu_list .= '</div>' ."\n";
$menu_list .= '</div><!-- /.container-fluid -->' ."\n";
$menu_list .= '</nav>' ."\n";
} else {
$menu_list = '<!-- no menu defined in location "'.$theme_location.'" -->';
}
echo $menu_list;
}
?>

Related

How to make a Wordpress Walker Class for a vertical sidebar menu with Bootstrap 4 Accordion?

I'm trying to build my own Walker_Nav_Menu class for a vertical sidebar menu inside my Wordpress Theme. I'm using Bootstrap 4 as a Framework.
My goal is to build something like the following html with the Walker class.
<div id="accordion">
<ul>
<li>
<a href="#" class="custom-class" id="indiceheading-1" data-toggle="collapse" data-target="#indicecollapse-1" aria-expanded="true" aria-controls="indicecollapse-1">
Link 1 but it's an accordion
</a>
<ul id="indicecollapse-1" class="collapse show" aria-labelledby="indiceheading-1" data-parent="#sidebarIndice">
<li>Link inside the dropdown</li>
</ul>
</li>
<li>Link 2</li>
<li>Link 3</li>
<li>
<a href="#" class="collapsed" id="indiceheading-2" data-toggle="collapse" data-target="#indicecollapse-2" aria-expanded="false" aria-controls="indicecollapse-2">
Link 4 but it's an accordion
</a>
<ul id="indicecollapse-2" class="collapse" aria-labelledby="indiceheading-2" data-parent="#sidebarIndice">
<li>Link inside the second dropdown</li>
</ul>
</li>
</ul>
</div>
The walker class I wrote is the following one (but it's not working)
<?php
class Walker_Indice extends Walker_Nav_Menu{
public function start_lvl( &$output, $depth = 0, $args = array() ) {
$indent = str_repeat("\t",$depth);
$output .= "\n$indent<ul class=\"collapse deph_$depth\">\n";
} //start_lvl
public function end_lvl( &$output, $depth = 0, $args = array() ) {
$indent = str_repeat("\t", $depth);
$output .= "$indent</ul>\n"; //da cambiare a seconda di come apro in start_lvl
} //end_lvl
function start_el(&$output, $item, $depth=0, $args=array(), $id=0){
$indent = ($depth) ? str_repeat("\t",$depth): '';
$li_attributes='';
$class_names=$value='';
$classes = empty( $item->classes ) ? array() : (array) $item->classes;
$classes[] = ($item->current || $item->current_item_anchestor)? 'active' : '';
$classes[] = 'menu-item-'.$item->ID;
$class_names = join(' ', apply_filters('nav_menu_css_class', array_filter( $classes ), $item, $args ));
$class_names = ' class="' . esc_attr($class_names) . '"';
$id = apply_filters('nav_menu_item_id', 'menu-item-'.$item->ID, $item, $args);
$id = strlen( $id ) ? ' id="' . esc_attr( $id ) . '"' : '';
$output .= $indent . '<li' . $id . $value . $class_names . $li_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) . '"' : '';
if($args->walker->has_children){
$attributes .= ( $args->walker->has_children ) ? ' class="nav-link dropdown-toggle" data-toggle="dropdown"' : '';
}else{
$attributes .= ' class="nav-link"';
}
$item_output = $args->before;
$item_output .= '<a' . $attributes . '>';
$item_output .= $args->link_before . apply_filters( 'the_title', $item->title, $item->ID ) . $args->link_after;
$item_output .= $args->after;
$output .= apply_filters ( 'walker_nav_menu_start_el', $item_output, $item, $depth, $args );
} //start_el
}
Can someone help me with this? I'm new and I can't find a tutorial for this, because every tutorials on the web are for normal Bootstrap navbar, but with accordions I need dynamic data-target, aria-controls ecc.
Thanks for your help.

Twitter Bootstrap Navbar align not working properly

im generating a bootstrap navbar using codeigniter, its working fine but i want the admin link to be aligned to the right. here is my code:
function get_menu ($array, $child = FALSE)
{
$CI =& get_instance();
$str = '';
if (count($array)) {
$str .= $child == FALSE ? '<ul class="nav navbar-left navbar-custom">' . PHP_EOL : '</ul>' . PHP_EOL;
foreach ($array as $item) {
$active = $CI->uri->segment(1) == $item['slug'] ? TRUE : FALSE;
if (isset($item['children']) && count($item['children'])) {
$str .= $active ? '<li class="dropdown active">' : '<li class="dropdown">';
$str .= '<a class="dropdown-toggle" data-toggle="dropdown" href="' . site_url(e($item['slug'])) . '">' . e($item['title']);
$str .= '<b class="caret"></b></a>' . PHP_EOL;
$str .= get_menu($item['children'], TRUE);
}
else {
$str .= $active ? '<li class="active">' : '<li>';
$str .= '' . e($item['title']) . '';
}
// Closing tags
$str .= '</li>' ;
}
//add dashboard link to the right of menu for login
$str .= '<li>' . '<p class="navbar-text navbar-right"><a
`href="admin/dashboard" class="navbar-link"> ADMIN</a></p></li>' . PHP_EOL;
$str .= '</ul>' . PHP_EOL;
}
im getting a navbar with required links but its all inline. any help is aappreciated. Cheers
This is because of where you are adding the navbar-right class. You have to add it to an ul element. Change your second to last string:
$str .= '<li>' . '<p class="navbar-text navbar-right"><a `href="admin/dashboard" class="navbar-link"> ADMIN</a></p></li>' . PHP_EOL;
To something along these lines:
<ul class="nav navbar-nav navbar-right">
<li> ADMIN</li>
</ul>
And do not add it inside of your current ul element, that will also not work; you need to close the navbar-left class then add the navbar-right.
Looking something like this:
UPDATE
I think I got it, you do not have the nav element around your navbar, and that is probably what is causing the issues with alignments...
<?php
function get_menu ($array, $child = FALSE)
{
$CI =& get_instance();
$str = '';
if (count($array)) {
$str .= $child == FALSE ? '<nav class="navbar navbar-default"> <ul class="nav navbar-nav navbar-custom">' . PHP_EOL; // create the <nav> element
foreach ($array as $item) {
$active = $CI->uri->segment(1) == $item['slug'] ? TRUE : FALSE;
if (isset($item['children']) && count($item['children'])) {
$str .= $active ? '<li class="dropdown active">' : '<li class="dropdown">';
$str .= '<a class="dropdown-toggle" data-toggle="dropdown" href="' . site_url(e($item['slug'])) . '">' . e($item['title']);
$str .= '<b class="caret"></b></a>' . PHP_EOL;
$str .= get_menu($item['children'], TRUE);
}
else {
$str .= $active ? '<li class="active">' : '<li>';
$str .= '' . e($item['title']) . '';
}
// Closing tags
$str .= '</li>' ;
}
$str .= '</ul>' . PHP_EOL;
//add dashboard link to the right of menu for login
$str .= '<ul class="nav navbar-nav navbar-right">
<li> ADMIN</li>
</ul>' . PHP_EOL;
// add the nav closing tag
$str .= '</nav>' . PHP_EOL;
}
?>

PHP While Loop wrapping every 4 results with a li

i am trying to wrap each 4 results inside a LI and repeat for every 4 items like
<li>
<div>item 1</div>
<div>item 2</div>
<div>item 3</div>
<div>item 4</div>
</li>
PHP so far.... the loop ive attempted is of course not working :)
if ( $query->have_posts() ) {
$opnews .= '<ul class="newsitems orbit-slides-container">';
$count = 0;
while ( $query->have_posts() ) : $query->the_post();
$post_id = get_the_ID();
$opnews_item_data = get_post_meta( $post_id, 'opnews_item', true );
if ($i%4 == 1) {
$opnews .= '<li>';
}
$opnews .= '<div class="columns large-3 small-12 medium-3">';
$opnews .= '<div class="panel green opacity-change">';
$opnews .= '<h1>' . get_the_title() . '</h1>';
$opnews .= get_the_content_with_formatting();
$opnews .= '</div>';
$opnews .= '</div>';
if ($count%4 == 0) {
$opnews .= '</li>';
}
endwhile;
$opnews .= '</ul>';
wp_reset_postdata();
}
You are using $i and $count, so pick only one.
Then you have to increment it between your <li> to get it working.
And finally, you should check, once you finished the loop, that the last <li> has been echoed or you will get some trouble (a missing </li>)
$array = range(1, 9);
$i = 0;
foreach ($array as $val) {
if ($i%4 == 0) echo '<li>';
$i++;
echo $val;
if ($i%4 == 0) echo '</li>';
}
if ($i%4 != 0) echo '</li>';
Output :
<li>
1 2 3 4
</li>
<li>
5 6 7 8
</li>
<li>
9
</li>
The modulus operator (%) divides the number and returns the remainder. So, your line if ($i%4 == 1) probably isn't what you're after, as if it's every 4th row, you'll want it with no remainder.
The $count%4 == 0 line also doesn't make much sense to me, as you're not incrementing the number. You're also not incrementing $i.
Try the following:
if ( $query->have_posts() ) {
$opnews .= '<ul class="newsitems orbit-slides-container">';
$i = 0;
while ( $query->have_posts() ) : $query->the_post();
$post_id = get_the_ID();
$opnews_item_data = get_post_meta( $post_id, 'opnews_item', true );
if ($i%4 == 0) {
if ($i != 0){
$opnews .= '</li>';
}
$opnews .= '<li>';
}
$opnews .= '<div class="columns large-3 small-12 medium-3">';
$opnews .= '<div class="panel green opacity-change">';
$opnews .= '<h1>' . get_the_title() . '</h1>';
$opnews .= get_the_content_with_formatting();
$opnews .= '</div>';
$opnews .= '</div>';
$i++;
endwhile;
$opnews .= '</li>';
$opnews .= '</ul>';
wp_reset_postdata();
}
It's not working because you never change count. Count is always 0, so $count % 4 == 0 is always true. Also, unless it's somewhere else you haven't defined i.
Use only count (or only i).
if ($count % 4 == 0) {
$opnews .= '<li>';
}
DO STUFF HERE
$count += 1
if ($count % 4 == 0) {
$opnews .= '</li>';
}
It looks like you're mixing both $i and $count. One of them you're using the modulous operator and comparing if the remainder after division is 1, and the other you're comparing if the remainder is 0. Neither of them seems to be incrementing (and $i doesn't look to be defined from the snippet you've provided).
Choose one, $count, and compare it with 0 using the modulous and be sure to increment it within the loop:
if ($count % 4 == 0) {
$opnews .= '<li>';
}
// ...
$count++;
if ($count % 4 == 0) {
$opnews .= '</li>';
}

How to output a list of social icons in custom function?

I have an unordered list of social icons I would like to output, but am stumped on how I would I do it with my current function (use an array, $figure?) -
So my raw code is currently (which checks if a field is filled, and if so shows the icon on the front-end) -
<?php if ( get_post_meta( $post->ID, 'member_twitter', true ) ) { ?>
<li><i class="fa fa-twitter"></i></li>
<?php } if ( get_post_meta( $post->ID, 'member_facebook', true ) ) { ?>
<li><i class="fa fa-facebook"></i></li>
<?php } if ( get_post_meta( $post->ID, 'member_googleplus', true ) ) { ?>
<li><i class="fa fa-google-plus"></i></li>
<?php } ?>
Now I would like to insert these list items into the following (and looping through them) -
if ($layout_style == "style-one") {
$html .= "<div class='team-member'>";
$html .= "<h3 class='member-name'>$title</h3>";
$html .= "<div class='member-role'>$member_role</div>";
$html .= "<ul class='social-icons'>";
$html .= "</ul>";
$html .= "</div>";
}
Have tried a few unsuccessful ways already.
thanks
I think I know what you are asking for. Let me know if I missed the mark:
$socials = array(
array('twitter', 'Twitter', 'twitter'),
array('facebook', 'FaceBook', 'facebook'),
array('googleplus', 'Google Plus', 'google-plus'),
);
if ($layout_style == "style-one") {
$html .= "<div class='team-member'>";
$html .= "<h3 class='member-name'>$title</h3>";
$html .= "<div class='member-role'>$member_role</div>";
$html .= "<ul class='social-icons'>";
foreach ($socials as $social) {
if (get_post_meta($post->ID, 'member_' . $social[0], true)) {
$html .= "<li><i class=\"fa fa-" . $social[2] . "\"></i></li>";
}
}
$html .= "</ul>";
$html .= "</div>";
}

Wordpress menu design

I require the following output for my site menus for my theme, which I generated using Weebly.
<!--Top level-->
<div class="nav-container">
<ul class='wsite-menu-default'>
<li id='active'>
<a href='/'>Home</a></li>
<li id='pg460790036268222251'>
<a href='/about.html'>About US</a>
<!--Second Level-->
<div class='wsite-menu-wrap' style='display:none'>
<ul class='wsite-menu'>
<li id='wsite-nav-887406923503161985'>
<a href='/our-community.html' >
<span class='wsite-menu-title'>Our Community</span>
</a></li>
<li id='wsite-nav-920389812461078079'>
<a href='/our-approach.html' >
<span class='wsite-menu-title'>Our Approach</span>
<span class='wsite-menu-arrow'>></span></a>
<!--Third level-->
<div class='wsite-menu-wrap' style='display:none'>
<ul class='wsite-menu'>
<li id='wsite-nav-351232458403900697'>
<a href='/research.html' >
<span class='wsite-menu-title'>Research</span></a>
</li>
<li id='wsite-nav-824453669863261400'>
<a href='/advocacy.html' >
<span class='wsite-menu-title'>Advocacy</span></a>
</li>
<li id='wsite-nav-802033955677651213'>
<a href='/publications.html' >
<span class='wsite-menu-title'>Publications</span></a>
</li>
</ul>
</div>
<!--Repeat above block as required -->
........................
<!--End Third-->
</li>
<li id='wsite-nav-307985062116431544'>
<a href='/our-constitution.html' >
<span class='wsite-menu-title'>Our Constitution</span></a>
</li>
<li id='wsite-nav-347537193311521165'>
<a href='/job-opportunities.html' >
<span class='wsite-menu-title'>Job Opportunities</span></a>
</li>
</ul>
</div>
<!--Repeat above block as required -->
..............
<!--End Second-->
</li>
<!--Repeat above block as required -->
..............
<!--End Top-->
</ul></div>
Now I need to port this over to a Wordpress system. I am familiar with menu basics, but need to know how to configure a Walker or custom function for this task for my theme. All jQuery, CSS scripts are in place, all I need to do is nest the following output as it is with the respective ids, classes and specified inline styling. I have created the menu hierarchy at Wordpress admin like I did in Weebly. I have been searching for examples but cant seem to find one that fits my requirement. Below is my Walker function.
class my_menu_walker extends Walker_Nav_Menu
{
function start_lvl(&$output, $depth)
{
$indent = str_repeat("\t", $depth);
if($depth === 0)
{
$output .= "\n$indent<ul class='wsite-menu-default'>\n";
}
else
{
$output .= "\n$indent<ul class='wsite-menu-default' style='display:none'>\n";
}
}
function start_el(&$output, $item, $depth, $args)
{
global $wp_query;
$indent = ($depth)? str_repeat("\t", $depth): '';
$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 ) .'"' : '';
//if second level menus
/*$unit_output = $args->before;*/
$unit_output = "<a".$attributes.">";
$unit_output .= /*$args->link_before.*/ "<span>".apply_filters( 'the_title', $item->title, $item->ID )."</span>";
/*$unit_output .= $args->link_after;*/
$unit_output .= "</a>";
/*$unit_output .= $args->after;*/
//for top menu page navigation
if($item->current)
{
$output .= $indent."<li id='active'>";
}
else
{
$output .= $indent."<li id='pg".$item->ID."'>";
}
$output .= apply_filters( 'walker_nav_menu_start_el', $unit_output, $item, $depth, $args );
}
}
At the top of functions.php
add_theme_support( 'menus' );
And in header.php
<?php wp_nav_menu(array(
'theme_location' => 'header-menu',
'container' => 'div',
'container_class' => 'wsite-menu-default',
'menu_class' => 'nav-container',
'echo' => true,
'walker'=> new my_menu_walker()
)); ?>
My $depth is not receiving the correct data, please advise
function start_lvl(&$output, $depth)
{
$indent = str_repeat("\t", $depth);
if($depth > 1)
{
$output .= "\n$indent<ul class='wsite-menu'>\n";
}
else
{
$output .= "\n$indent<ul class='wsite-menu-default'>\n";
}
}

Categories