How to Create Multi Level Dynamic Menu In Laravel Treeview

Laravel 6 , Laravel , Laravel 7

Nicesnippets

54109

22-01-2020


Hii Guys,

Today, I will explain how can create dynamic multi level menu in laravel we will create example of multi level dynamic menu in laravel you can easy to make many level dynamic menu in laravel. i will show parents and child menu with nested tree view structure in Laravel application.

In this tutorial i simple create "menus" table and manage end level of parents and child menu with nested tree view structure in Laravel application. I use jquery for make tree view layout and child relationship with menu model for hierarchical data. I also add form for create new menu in tree view.I also create dynamic drop down menu using bootstrap nav.

If you are new in laravel then also you can do it simple and also simply customize it because this tutorial from scratch. You can simple following bellow step, you will multi level dynamic menu in your application as bellow preview and also you can check demo.

here following example step of multi level dynamic menu in laravel treeview

Step 1 : Install Laravel 6 Application

we are going from scratch, So we require to get fresh Laravel application using bellow command, So open your terminal OR command prompt and run bellow command:

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

Database Configuration

In this step, we require to make database configuration, you have to add following details on your .env file.

1.Database Username

1.Database Password

1.Database Name

In .env file also available host and port details, you can configure all details as in your system, So you 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

In this step we have to create migration and model for menus table using Laravel 6 php artisan command, so first fire bellow command:

php artisan make:model Menu -m

After this command you have to put bellow code in your migration file for create menus table.

following path:/database/migrations/2020_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');

}

}

Now we require to run migration be bellow command:

php artisan migrate

After you have to put bellow code in your model file for create Menu table.

following path:/app/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

In this is step we need to create route for tree menu show layout file , 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

here this step now we should create new controller as MenuController,So run bellow command for generate new controller

php artisan make:controller MenuController

now this step, this controller will manage menu layout and create menu with validation with post request,bellow content in controller file. 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\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

In this step, we have to create 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

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 - nicesnippets.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 - nicesnippets.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>

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>

After This both blade file will help to render dynamic drop down menu view file, so let's create both file view file and 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

Step 6: Add CSS and JS File

In last step, we have to add one css file and one js file for treeview design. 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 we are ready to run our example so run bellow command so quick run:

php artisan serve

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

It will help you...


Recommended Posts