PHP Bootstrap 4 navigation menu with sub-menu's

后端 未结 2 1514
小鲜肉
小鲜肉 2021-01-07 12:20

ORIGINAL POST

I want to create a navigation menu in PHP with Bootstrap 4. Problem is that one of the

  • \'s is not right (the on
  • 相关标签:
    2条回答
    • 2021-01-07 12:53

      I added menu to the database and check if it's 0 or 1. I have dropped the sub-sub menu's, but I will update this post if I add them.

      function menu_builder($pdo, $parent_id) {
          $sql = $pdo->prepare("SELECT * FROM menus");
          if ($sql->execute()) {
              while ($row = $sql->fetch(PDO::FETCH_ASSOC)) {
                   $array[$row['parent_id']][] = $row;
              }
              main_menu($array);
          }
      }
      function main_menu ($array, $parent_id = 0) {
          if (!empty($array[$parent_id])) {
              foreach ($array[$parent_id] as $item) {
                  if ($item['menu'] == '0') {
                      echo "  <li class=\"nav-item\">" . PHP_EOL;
                      echo "    <a class=\"nav-link\" href=\"#\">" . $item['menu_naam'] . "</a>" . PHP_EOL;
                      main_menu($array, $item['id']);
                      echo "  </li>" . PHP_EOL;
                  }
                  elseif ($item['menu'] == '1') {
                      echo "  <li class=\"nav-item dropdown\"><a class=\"nav-link dropdown-toggle\" href=\"#\" id=\"navbarDropdown\" role=\"button\" data-toggle=\"dropdown\" aria-haspopup=\"true\" aria-expanded=\"false\">" . $item['menu_naam'] . "</a>" . PHP_EOL;
                      sub_menu($array, $item['id']);
                      echo "  </li>" . PHP_EOL;
                  }
              }
              //echo "</div>" . PHP_EOL;
              echo "</li>" . PHP_EOL;
          }
      }
      function sub_menu ($array, $parent_id) {
          if (!empty($array[$parent_id])) {
              echo "    <div class=\"dropdown-menu\" aria-labelledby=\"navbarDropdown\">" . PHP_EOL;
              foreach ($array[$parent_id] as $item) {
                  echo "      <a class=\"dropdown-item\" href=\"" . $item['url'] . "\">" . $item['menu_naam'] . "</a>" . PHP_EOL;
              }
              echo "    </div>" . PHP_EOL;
          }
      }
      
      ?>
      <header class="navbar navbar-dark bg-dark fixed-top navbar-expand-sm">
          <a class="navbar-brand" href="#">Webshop</a>
          <button class="navbar-toggler" style="background: #000000" type="button" data-toggle="collapse" data-target="#navbar-header" aria-controls="navbar-header">
              &#9776;
          </button>
          <div class="navbar-collapse collapse show" id="navbar-header">
      
              <?php
              echo "<ul class=\"navbar-nav mr-auto\">";
              echo menu_builder($pdo, 0);
              echo "</ul>" . PHP_EOL;    
              ?>
          </div>
      </header>
      

      EDIT: To have sub-menu's the code looks like this and you need the following css too.

      function menu_builder($pdo, $parent_id) {
          $sql = $pdo->prepare("SELECT * FROM menus");
          if ($sql->execute()) {
              while ($row = $sql->fetch(PDO::FETCH_ASSOC)) {
                   $array[$row['parent_id']][] = $row;
              }
              main_menu($array);
          }
      }
      function main_menu ($array, $parent_id = 0) {
          if (!empty($array[$parent_id])) {
              foreach ($array[$parent_id] as $item) {
                  if ($item['menu'] == '0') {
                      echo "            <li class=\"nav-item\">" . PHP_EOL;
                      echo "                <a class=\"nav-link\" href=\"" . $item['url'] . "\">" . $item['menu_naam'] . "</a>" . PHP_EOL;
                      main_menu($array, $item['id']);
                      echo "            </li>" . PHP_EOL;
                  }
                  elseif ($item['menu'] == '1') {
                      echo "            <li class=\"nav-item dropdown\">". PHP_EOL;
                      echo "                <a class=\"nav-link dropdown-toggle\" href=\"" . $item['url'] . "\" id=\"navbarDropdown\" role=\"button\" data-toggle=\"dropdown\" aria-haspopup=\"true\" aria-expanded=\"false\">" . $item['menu_naam'] . "</a>" . PHP_EOL;
                      sub_menu($array, $item['id']);
                      echo "            </li>" . PHP_EOL;
                  }
              }
          }
      }
      function sub_menu ($array, $parent_id) {
          if (!empty($array[$parent_id])) {
              echo "                <div class=\"dropdown-menu\" aria-labelledby=\"navbarDropdown\">" . PHP_EOL;
              foreach ($array[$parent_id] as $item) {
                  if ($item['sub_menu'] == '0') { 
                      echo "                    <a class=\"dropdown-item\" href=\"" . $item['url'] . "\">" . $item['menu_naam'] . "</a>" . PHP_EOL;
                  }
                  elseif ($item['sub_menu'] == '1') {
                      echo "                    <div class=\"dropdown-submenu\">" . PHP_EOL;
                      echo "                        <a class=\"dropdown-item dropdown-toggle\" href=\"" . $item['url'] . "\">" . $item['menu_naam'] . "</a>" . PHP_EOL;
                      sub_sub_menu($array, $item['id']);
                      echo "                    </div>" . PHP_EOL;
                  }
              }
              echo "                </div>" . PHP_EOL;
          }
      }
      function sub_sub_menu ($array, $parent_id) {
          if (!empty($array[$parent_id])) {
              echo "                    <div class=\"dropdown-menu\" aria-labelledby=\"navbarDropdown\">" . PHP_EOL;
              foreach ($array[$parent_id] as $item) {
                  echo "                        <a class=\"dropdown-item\" href=\"" . $item['url'] . "\">" . $item['menu_naam'] . "</a>" . PHP_EOL;
              }
          }
          echo "                    </div>" . PHP_EOL;
      }
      

      The CSS you need for the sub-menu's because bootstrap doesn't have support for it by default (https://stackoverflow.com/a/45755948/2877035):

      .dropdown-submenu {
        position: relative;
      }
      
      .dropdown-submenu a::after {
        transform: rotate(-90deg);
        position: absolute;
        right: 6px;
        top: .8em;
      }
      
      .dropdown-submenu .dropdown-menu {
        top: 0;
        left: 100%;
        margin-left: .1rem;
        margin-right: .1rem;
      }
      

      and the jQuery:

      $('.dropdown-menu a.dropdown-toggle').on('click', function(e) {
          if (!$(this).next().hasClass('show')) {
              $(this).parents('.dropdown-menu').first().find('.show').removeClass("show");
          }
          var $subMenu = $(this).next(".dropdown-menu");
          $subMenu.toggleClass('show');
          $(this).parents('li.nav-item.dropdown.show').on('hidden.bs.dropdown', function(e) {
              $('.dropdown-submenu .show').removeClass("show");
          });
          return false;
      });
      
      0 讨论(0)
    • 2021-01-07 13:09

      I have maked some changes for bootstrap 4.1

      <style type="text/css">
          .navbar .dropdown-toggle, .navbar .dropdown-menu a {
              cursor: pointer;
          }
      
          .navbar .dropdown-item.active, .navbar .dropdown-item:active {
              color: inherit;
              text-decoration: none;
              background-color: inherit;
          }
      
          .navbar .dropdown-item:focus, .navbar .dropdown-item:hover {
              color: #16181b;
              text-decoration: none;
              background-color: #f8f9fa;
          }
      
          @media (min-width: 767px) {
              .navbar .dropdown-toggle:not(.nav-link)::after {
                  display: inline-block;
                  width: 0;
                  height: 0;
                  margin-left: .5em;
                  vertical-align: 0;
                  border-bottom: .3em solid transparent;
                  border-top: .3em solid transparent;
                  border-left: .3em solid;
              }
          }
      </style>
      <script type="text/javascript">
          $(document).ready(function () {
              $('.navbar .dropdown-item').on('click', function (e) {
                  var $el = $(this).children('.dropdown-toggle');
                  var $parent = $el.offsetParent(".dropdown-menu");
                  $(this).parent("li").toggleClass('open');
      
                  if (!$parent.parent().hasClass('navbar-nav')) {
                      if ($parent.hasClass('show')) {
                          $parent.removeClass('show');
                          $el.next().removeClass('show');
                          $el.next().css({"top": -999, "left": -999});
                      } else {
                          $parent.parent().find('.show').removeClass('show');
                          $parent.addClass('show');
                          $el.next().addClass('show');
                          $el.next().css({"top": $el[0].offsetTop, "left": $parent.outerWidth() - 4});
                      }
                      e.preventDefault();
                      e.stopPropagation();
                  }
              });
      
              $('.navbar .dropdown').on('hidden.bs.dropdown', function () {
                  $(this).find('li.dropdown').removeClass('show open');
                  $(this).find('ul.dropdown-menu').removeClass('show open');
              });
      
          });
      </script>
      
      <?php function menu_builder1($db, $parent_id) {
          $sql = $db->prepare("SELECT * FROM menu WHERE status = 1 ORDER BY position ASC");
          if($sql->execute()) {
              while ($row = $sql->fetch(PDO::FETCH_ASSOC)) {
                  $array[$row['menu_sub_id']][] = $row;
              }
              main_menu1($array);
          }
      }
      function main_menu1($array, $parent_id = false) {
          if(!empty($array[$parent_id])) {
              foreach ($array[$parent_id] as $item) {
                  if ($item['dropdown'] == false) {
                      echo '<li class="nav-item active"><a class="nav-link" href="' . $item['href'] . '">' . $item['name'] . '</a></li>';
                  }
                  elseif ($item['dropdown'] == true) {
                      echo '<li class="nav-item dropdown"><a class="nav-link dropdown-toggle" id="dropdown2" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">' . $item['name'] . '</a>';
                      sub_menu1($array, $item['menu_id']);
                      echo '</li>';
                  }
              }
          }
      }
      function sub_menu1($array = array(), $parent_id = false) {
          if(!empty($array[$parent_id])) {
              echo '<ul class="dropdown-menu" aria-labelledby="dropdown2">';
              foreach ($array[$parent_id] as $item) {
                  if ($item['dropdown'] == false) {
                      echo '<li class="dropdown-item"><a href="' . $item['href'] . '">' . $item['name'] . '</a></li>';
                  }
                  elseif ($item['dropdown'] == true) {
                      echo '<li class="dropdown-item dropdown"><a class="dropdown-toggle" id="dropdown2-1" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">' . $item['name'] . '</a>';
                      sub_sub_menu1($array, $item['menu_id']);
                      echo '</li>';
                  }
              }
              echo "</ul>";
          }
      }
      
      function sub_sub_menu1($array = array(), $parent_id = false) {
          if(!empty($array[$parent_id])) {
              echo '<ul class="dropdown-menu" aria-labelledby="dropdown2-1">';
              foreach ($array[$parent_id] as $item) {
                  if ($item['dropdown'] == false) {
                      echo '<li class="dropdown-item"><a href="' . $item['href'] . '">' . $item['name'] . '</a></li>';
                  }
              }
              echo "</ul>";
          }
      }
      ?>
      <div class="navbar navbar-expand-md navbar-dark bg-dark mb-4" role="navigation">
          <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarCollapse" aria-controls="navbarCollapse" aria-expanded="false" aria-label="Toggle navigation">
              <span class="navbar-toggler-icon"></span>
          </button>
          <div class="collapse navbar-collapse" id="navbarCollapse">
              <ul class="navbar-nav mr-auto">
                  <?=menu_builder1($db, 0)?>
              </ul>
          </div>
      </div>
      

      also some SQL info

      CREATE TABLE `menu` (
          `menu_id` int(11) NOT NULL,
          `menu_sub_id` int(11) NOT NULL,
          `added` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
          `status` int(1) NOT NULL DEFAULT '1',
          `href` varchar(150) NOT NULL,
          `class` varchar(150) NOT NULL,
          `position` int(3) NOT NULL,
          `name` varchar(150) NOT NULL,
          `description` varchar(500) NOT NULL,
          `dropdown` int(11) NOT NULL,
          `sub_menu` int(1) NOT NULL,
          `sub_sub_menu` int(1) NOT NULL
      ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
      
      ALTER TABLE `menu`
          ADD PRIMARY KEY (`menu_id`);
      
      ALTER TABLE `menu` 
          MODIFY `menu_id` int(11) NOT NULL AUTO_INCREMENT;
      COMMIT;
      
      0 讨论(0)
    提交回复
    热议问题