How to Create Multi Level Dynamic Menu Treeview In Laravel?

Share Me
  •  
  •  
  •  
  • 1
  •  
  •  
  •  
  •  
  •  
  •  
  •  
    1
    Share

Today now in this article, I will show you an example of how can we create a dynamic multi level menu in laravel applications? So here i will create an example of how to create a multi level dynamic menu in laravel. So from here we can an easy to make multiple level dynamic menus in laravel applications. Now here i will show you a parents and child menu and also with a nested tree view structure in our Laravel application.

So here now in this tutorial i will show you a simple create “menus” table and it will manage end level of parents and child menu also with a nested tree view structure in Laravel application. Now here I will use jquery for make tree to view layout and also child relationship with menu model for hierarchical data. Now so here I also add form for create a new menu in tree view. And i also create a dynamic drop down menu by using bootstrap nav.

how to create multi level dynamic menu in laravel?

Now If you are new in laravel framework. Then also you can do it so simple and also very simply customize it because of this tutorial will make from scratch for you. So here you can simple following bellow step, we will do multi level dynamic menu in our application as bellow preview and also we can check demo.

So here need to follow example step of multi level dynamic menu in laravel treeview

Step 1 : Install Laravel 8 Application

So here i am going from scratch, So now i need to get a fresh Laravel application by using bellow command, So please open your terminal OR command prompt andthen run bellow command:

composer create-project --prefer-dist laravel/laravel blog
Database Configuration

So now in this step, we need to make database configuration in our project, we need to add the following details on our .env file.

1.Database Username

2.Database Password

3.Database Name

So now In .env file also available host and port details, we can also configure all details as in our system, So we can put like as bellow:

following path: .env
DB_HOST=localhost
DB_DATABASE=homestead
DB_USERNAME=homestead
DB_PASSWORD=secret
Step 2: Create menus Table and Model

So now in this step we need to create a migration file and also with a model for menus table by using Laravel 8 php artisan command, so need to fire bellow command:

php artisan make:model Menu -m

So after this command we need to put bellow code in our migration file for create menus table.

following path:/database/migrations/2021_01_10_102325_create_menus_table.php

<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateMenusTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('menus', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->string('title');
            $table->integer('parent_id');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('menus');
    }
}

So now we need to run migration be bellow command:

php artisan migrate

Now after that we have to put bellow code in our model file for create Menu table.

following path:/app/Models/Menu.php
<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Menu extends Model
{
    protected $fillable = ['title','parent_id'];

    public function childs() {
        return $this->hasMany('App\Menu','parent_id','id') ;
    }
}

Step 3: Create Route

So now in this is step we need to create a route for tree menu show layout file , so create menu for post method

route and show dynamic menus.

following path:/routes/web.php

Route::get('menus','MenuController@index');
Route::get('menus-show','MenuController@show');
Route::post('menus','MenuController@store')->name('menus.store');
Step 4: Create Controller

So here in this step now we should create a new controller as name MenuController,So just need to run bellow command for generate new controller

php artisan make:controller MenuController

That’s good ,now in this step, on this controller will manage menu layout and also create menu with validation with post request, in bellow content in controller file. So now i added three method in this controller as listed bellow:

1)index()

2)store()

3)show()

following path:/app/Http/Controllers/MenuController.php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Models\Menu;

class MenuController extends Controller
{
    public function index(){
        $menus = Menu::where('parent_id', '=', 0)->get();
        $allMenus = Menu::pluck('title','id')->all();
        return view('menu.menuTreeview',compact('menus','allMenus'));
    }

    public function store(Request $request)
    {
        $request->validate([
           'title' => 'required',
        ]);

        $input = $request->all();
        $input['parent_id'] = empty($input['parent_id']) ? 0 : $input['parent_id'];
        Menu::create($input);
        return back()->with('success', 'Menu added successfully.');
    }

    public function show()
    {
        $menus = Menu::where('parent_id', '=', 0)->get();
        return view('menu.dynamicMenu',compact('menus'));
    }
}
Step 5: Create View

Now in this step, i have to create a menu folder in total four blade file as listed bellow:

1)menuTreeview.blade.php

2)manageChild.blade.php

3)dynamicMenu.blade.php

4)menusub.blade.php

So now this both blade file will help to render menu tree structure, so let’s create both file view file and put bellow code.

following path:/resources/views/menu/menuTreeview.blade.php
<!DOCTYPE html>
<html>
<head>
   <title>Multi Level Dynamic Menu In Laravel Treeview - codingspoint.com</title>
   <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.11.2/css/all.min.css" />
   <link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.4.1/css/bootstrap.css">
   <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
   <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script>
   <link href="/css/treeview.css" rel="stylesheet">
</head>
<body class="bg-dark">
<div class="container">
   <div class="row">
      <div class="col-md-10 offset-md-1 mt-4">
         <div class="card">
            <div class="card-header">
               <h5>Multi Level Dynamic Menu In Laravel Treeview - codingspoint.com</h5>
            </div>
            <div class="card-body">
               <div class="row">
                  <div class="col-md-6">
                     <h5 class="mb-4 text-center bg-success text-white ">Add New Menu</h5>
                     <form accept="{{ route('menus.store')}}" method="post">
                        @csrf
                         @if(count($errors) > 0)
                                  <div class="alert alert-danger  alert-dismissible">
                                      <button type="button" class="close" data-dismiss="alert">×</button>
                                      @foreach($errors->all() as $error)
                                              {{ $error }}<br>
                                      @endforeach
                                  </div>
                              @endif
                          @if ($message = Session::get('success'))
                           <div class="alert alert-success  alert-dismissible">
                               <button type="button" class="close" data-dismiss="alert">×</button>   
                                   <strong>{{ $message }}</strong>
                           </div>
                        @endif
                        <div class="row">
                           <div class="col-md-12">
                              <div class="form-group">
                                 <label>Title</label>
                                 <input type="text" name="title" class="form-control">   
                              </div>
                           </div>
                        </div>
                        <div class="row">
                           <div class="col-md-12">
                              <div class="form-group">
                                 <label>Parent</label>
                                 <select class="form-control" name="parent_id">
                                    <option selected disabled>Select Parent Menu</option>
                                    @foreach($allMenus as $key => $value)
                                       <option value="{{ $key }}">{{ $value}}</option>
                                    @endforeach
                                 </select>
                              </div>
                           </div>
                        </div>
                        <div class="row">
                           <div class="col-md-12">
                              <button class="btn btn-success">Save</button>
                           </div>
                        </div>
                     </form>
                  </div>
                  <div class="col-md-6">
                     <h5 class="text-center mb-4 bg-info text-white">Menu List</h5>
                      <ul id="tree1">
                         @foreach($menus as $menu)
                            <li>
                                {{ $menu->title }}
                                @if(count($menu->childs))
                                    @include('menu.manageChild',['childs' => $menu->childs])
                                @endif
                            </li>
                         @endforeach
                        </ul>
                  </div>
               </div>
            </div>
         </div>
      </div>
   </div>
</div>
<script src="/js/treeview.js"></script>
</body>
</html>

So here following include blade fille

following path:/resources/views/menu/manageChild.blade.php

<ul>
@foreach($childs as $child)
   <li>
       {{ $child->title }}
   @if(count($child->childs))
            @include('manageChild',['childs' => $child->childs])
        @endif
   </li>
@endforeach
</ul>

So after this both blade file will help to render dynamic drop down menu view file, so let’s start and create both file view file and now need to put bellow code.

following path:/resources/views/menu/dynamicMenu.blade.php
<!DOCTYPE html>
<html lang="en">
<head>
  <title>Bootstrap Example</title>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css">
  <link rel="stylesheet" type="text/css" href="https://bootstrapthemes.co/demo/resource/bootstrap-4-multi-dropdown-hover-navbar/css/bootstrap-4-hover-navbar.css">
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.16.0/umd/popper.min.js"></script>
  <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js"></script>
</head>
<body class="bg-dark">
<nav class="navbar navbar-expand-md navbar-light bg-light btco-hover-menu">
    <a class="navbar-brand" href="#">Nicesnippets.com</a>
    <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNavDropdown" aria-controls="navbarNavDropdown" aria-expanded="false" aria-label="Toggle navigation">
        <span class="navbar-toggler-icon"></span>
    </button>
    <div class="collapse navbar-collapse" id="navbarNavDropdown">
        <ul class="navbar-nav">
            @foreach($menus as $menu)
            <li class="nav-item dropdown">
                <a class="nav-link {{ count($menu->childs) ? 'dropdown-toggle' :'' }}" href="https://bootstrapthemes.co" id="navbarDropdownMenuLink" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
                   {{ $menu->title }}
                </a>
                <ul class="dropdown-menu " aria-labelledby="navbarDropdownMenuLink">
                  @if(count($menu->childs))
                    @include('menu.menusub',['childs' => $menu->childs])
                  @endif
                </ul>
            </li>
            @endforeach
        </ul>
    </div>
</nav>
<div style="position: absolute; left:2%; top:55%;">
  <h2 class="bg-white p-2 shadow-lg rounded">Multi Level Dynamic Menu In Laravel Treeview - Nicesnippets.com</h2>
</div>
</body>
</html>

here following include blade fille

following path:/resources/views/menu/menusub.blade.php

 @foreach($childs as $child)
 <li><a class="dropdown-item {{ count($child->childs) ? 'dropdown-toggle' :'' }}" href="#" style="border:1px solid #ccc;">{{ $child->title }}</a>
       @if(count($child->childs))
          <ul class="dropdown-menu">
              <li>
                 <a class="dropdown-item" href="#" style="position: absolute;">
                       @include('menu.menusub',['childs' => $child->childs])
                    </a>
                </li>
            </ul>
        @endif
   </li>
 @endforeach

Preview:Menu treeview hierarchical structure

how to create multi level dynamic menu in laravel
how to create multi level dynamic menu in laravel
Step 6: Add CSS and JS File

So now we are in last step, we need to add a one css file and also one js file for treeview design. So it I simply use bootsnipp css and js code, so let’s create css and js file as following path:

following path:public/css/treeview.css

.tree, .tree ul {
    margin:0;
    padding:0;
    list-style:none
}
.tree ul {
    margin-left:1em;
    position:relative
}
.tree ul ul {
    margin-left:.5em
}
.tree ul:before {
    content:"";
    display:block;
    width:0;
    position:absolute;
    top:0;
    bottom:0;
    left:0;
    border-left:1px solid
}
.tree li {
    margin:0;
    padding:0 1em;
    line-height:2em;
    color:#369;
    font-weight:700;
    position:relative
}
.tree ul li:before {
    content:"";
    display:block;
    width:10px;
    height:0;
    border-top:1px solid;
    margin-top:-1px;
    position:absolute;
    top:1em;
    left:0
}
.tree ul li:last-child:before {
    background:#fff;
    height:auto;
    top:1em;
    bottom:0
}
.indicator {
    margin-right:5px;
}
.tree li a {
    text-decoration: none;
    color:#369;
}
.tree li button, .tree li button:active, .tree li button:focus {
    text-decoration: none;
    color:#369;
    border:none;
    background:transparent;
    margin:0px 0px 0px 0px;
    padding:0px 0px 0px 0px;
    outline: 0;
}

This is require js file

following path:public/js/treeview.js
$.fn.extend({
    treed: function (o) {
      
      var openedClass = 'glyphicon-minus-sign';
      var closedClass = 'glyphicon-plus-sign';
      
      if (typeof o != 'undefined'){
        if (typeof o.openedClass != 'undefined'){
        openedClass = o.openedClass;
        }
        if (typeof o.closedClass != 'undefined'){
        closedClass = o.closedClass;
        }
      };
      
        /* initialize each of the top levels */
        var tree = $(this);
        tree.addClass("tree");
        tree.find('li').has("ul").each(function () {
            var branch = $(this);
            branch.prepend("");
            branch.addClass('branch');
            branch.on('click', function (e) {
                if (this == e.target) {
                    var icon = $(this).children('i:first');
                    icon.toggleClass(openedClass + " " + closedClass);
                    $(this).children().children().toggle();
                }
            })
            branch.children().children().toggle();
        });
        /* fire event from the dynamically added icon */
        tree.find('.branch .indicator').each(function(){
            $(this).on('click', function () {
                $(this).closest('li').click();
            });
        });
        /* fire event to open branch if the li contains an anchor instead of text */
        tree.find('.branch>a').each(function () {
            $(this).on('click', function (e) {
                $(this).closest('li').click();
                e.preventDefault();
            });
        });
        /* fire event to open branch if the li contains a button instead of text */
        tree.find('.branch>button').each(function () {
            $(this).on('click', function (e) {
                $(this).closest('li').click();
                e.preventDefault();
            });
        });
    }
});
/* Initialization of treeviews */
$('#tree1').treed();

Now finally we are ready to run our example so run bellow command so quick run:

php artisan serve

So need to open bellow URL to create menu on your browser:

http://localhost:8000/menus

Now you can open bellow URL to dropdown nav menu on your browser:

http://localhost:8000/menus-show

Read Also : Laravel 8 Eloquent Global Scope Tutorial Example

I hope it will help you. Also you can follow us on Facebook

About Shahriar Sagor

My name is Shahriar sagor. I'm a developer. I live in Bangladesh and I love to write tutorials and tips that will help to other Developer's. I am a big fan of PHP, Javascript, JQuery, Laravel, Codeigniter, VueJS, AngularJS and Bootstrap from the early stage.

View all posts by Shahriar Sagor →