Hii Dev,
In this blog, 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.
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 8 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
2.Database Password
3.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 8 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/Models/Menu.php
<?php
namespace App\Models;
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
<?php
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\MenuController;
/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/
Route::get('menus',[MenuController::class,'index']);
Route::get('menus-show',[MenuController::class,'show']);
Route::post('menus',[MenuController::class,'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
{
/**
* Write code on Method
*
* @return response()
*/
public function index(){
$menus = Menu::where('parent_id', '=', 0)->get();
$allMenus = Menu::pluck('title','id')->all();
return view('menu.menuTreeview',compact('menus','allMenus'));
}
/**
* Write code on Method
*
* @return response()
*/
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.');
}
/**
* Write code on Method
*
* @return response()
*/
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</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</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</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...