Laravel Category Treeview Hierarchical Structure Example

By Hardik Savani November 5, 2023 Category : PHP Laravel

Today, I am going to share with you how to create dynamic category tree view structure in Laravel 5 application using jquery. We sometime require to make tree view structure for category and subcategory in laravel 6, laravel 7, laravel 8, laravel 9 and laravel 10 project.

In this tutorial i simple create "categories" table and manage end level of parents and child category with nested tree view structure in Laravel application. I use jquery for make tree view layout and child relationship with category model for hierarchical data. I also add form for create new category in tree view.

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 get category tree view in your application as bellow preview and also you can check demo.

Preview:

Step 1: Install Laravel 5.3 Application

In first step, if you haven't laravel 5.3 application setup then we have to get fresh laravel 5.3 application. So run bellow command and get clean fresh laravel 5.3 application.

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

Step 2: Create Category Table and Model

In this step we have to create migration for categories table using Laravel 5.3 php artisan command, so first fire bellow command:

php artisan make:migration create_category_table

After this command you will find one file in following path database/migrations and you have to put bellow code in your migration file for create categories table.

use Illuminate\Support\Facades\Schema;

use Illuminate\Database\Schema\Blueprint;

use Illuminate\Database\Migrations\Migration;


class CreateCategoryTable extends Migration

{

/**

* Run the migrations.

*

* @return void

*/

public function up()

{

Schema::create('categories', function (Blueprint $table) {

$table->increments('id');

$table->string('title');

$table->integer('parent_id');

$table->timestamps();

});

}


/**

* Reverse the migrations.

*

* @return void

*/

public function down()

{

Schema::drop("categories");

}

}

After create "categories" table you should create Category model for categories, so first create file in this path app/Category.php and put bellow content in item.php file:

app/Category.php

<?php


namespace App;


use Illuminate\Database\Eloquent\Model;


class Category extends Model

{


public $fillable = ['title','parent_id'];


/**

* Get the index name for the model.

*

* @return string

*/

public function childs() {

return $this->hasMany('App\Category','parent_id','id') ;

}

}

Step 3: Create Route

In this is step we need to create two route one for render treeview and second for add new category file. so open your routes/web.php file and add following route.

routes/web.php

Route::get('category-tree-view',['uses'=>'CategoryController@manageCategory']);

Route::post('add-category',['as'=>'add.category','uses'=>'CategoryController@addCategory']);

Step 4: Create Controller

In this point, now we should create new controller call CategoryController in this path app/Http/Controllers/CategoryController.php. In this controller we will manage route method, i added two method in this controller as listed bellow:

1) manageCategory()

2) addCategory()

So, copy bellow code and put in your controller file.

app/Http/Controllers/CategoryController.php

<?php


namespace App\Http\Controllers;


use Illuminate\Http\Request;

use App\Http\Requests;

use App\Category;


class CategoryController extends Controller

{

/**

* Show the application dashboard.

*

* @return \Illuminate\Http\Response

*/

public function manageCategory()

{

$categories = Category::where('parent_id', '=', 0)->get();

$allCategories = Category::pluck('title','id')->all();

return view('categoryTreeview',compact('categories','allCategories'));

}


/**

* Show the application dashboard.

*

* @return \Illuminate\Http\Response

*/

public function addCategory(Request $request)

{

$this->validate($request, [

'title' => 'required',

]);

$input = $request->all();

$input['parent_id'] = empty($input['parent_id']) ? 0 : $input['parent_id'];

Category::create($input);

return back()->with('success', 'New Category added successfully.');

}


}

Step 5: Create View

In this step, we have to create total two blade file as listed bellow:

1. categoryTreeview.blade.php

2. manageChild.blade.php

This both blade file will help to render category tree structure, so let's create both file view file and put bellow code.

resources/views/categoryTreeview.blade.php

<!DOCTYPE html>

<html>

<head>

<title>Laravel Category Treeview Example</title>

<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.6.3/css/font-awesome.min.css" />

<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>

<link href="/css/treeview.css" rel="stylesheet">

</head>

<body>

<div class="container">

<div class="panel panel-primary">

<div class="panel-heading">Manage Category TreeView</div>

<div class="panel-body">

<div class="row">

<div class="col-md-6">

<h3>Category List</h3>

<ul id="tree1">

@foreach($categories as $category)

<li>

{{ $category->title }}

@if(count($category->childs))

@include('manageChild',['childs' => $category->childs])

@endif

</li>

@endforeach

</ul>

</div>

<div class="col-md-6">

<h3>Add New Category</h3>


{!! Form::open(['route'=>'add.category']) !!}


@if ($message = Session::get('success'))

<div class="alert alert-success alert-block">

<button type="button" class="close" data-dismiss="alert">×</button>

<strong>{{ $message }}</strong>

</div>

@endif


<div class="form-group {{ $errors->has('title') ? 'has-error' : '' }}">

{!! Form::label('Title:') !!}

{!! Form::text('title', old('title'), ['class'=>'form-control', 'placeholder'=>'Enter Title']) !!}

<span class="text-danger">{{ $errors->first('title') }}</span>

</div>


<div class="form-group {{ $errors->has('parent_id') ? 'has-error' : '' }}">

{!! Form::label('Category:') !!}

{!! Form::select('parent_id',$allCategories, old('parent_id'), ['class'=>'form-control', 'placeholder'=>'Select Category']) !!}

<span class="text-danger">{{ $errors->first('parent_id') }}</span>

</div>


<div class="form-group">

<button class="btn btn-success">Add New</button>

</div>


{!! Form::close() !!}


</div>

</div>


</div>

</div>

</div>

<script src="/js/treeview.js"></script>

</body>

</html>

resources/views/manageChild.blade.php

<ul>

@foreach($childs as $child)

<li>

{{ $child->title }}

@if(count($child->childs))

@include('manageChild',['childs' => $child->childs])

@endif

</li>

@endforeach

</ul>

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:

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;

}

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();

Ok, now you are ready to run and check your application.

I hope it can help you...

Tags :
Shares