Laravel Unlimited Hierarchical Category Tree View

By | June 8, 2019

This tutorial is about the Laravel Unlimited Hierarchical Category Tree View. You can use this code for an unlimited hierarchical category in admin panel and front-end. Same as Magento’s category hierarchy.

The first step you need to install the fresh latest version of Laravel in your local system for that follow the previous tutorial of CodesCompanion How to install Laravel 5.X

Follow this tutorial and install the fresh Laravel in your system.

Create and Migrate Category Table

In this step, we are going to create a category table using the terminal. For that run below command in your terminal.

php artisan make:migration create_category_table

After running this it will look like this.

category-table

This will create the migration table file in “app/database/migrations” folder. Now Open that file and you will see that this file already has this code and this code will be in the file automatically while that file will generate.

<?php

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('category', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->timestamps();
        });
    }

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

We are going to modify that code and the final output will look like this.

<?php

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->bigIncrements('id');
            $table->string('title');
            $table->integer('parent_id');
            $table->timestamps();
        });
    }

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

After update this file we need to migrate this table to the database for that run below code.

php artisan migrate

This will generate the table name “categories” in the database.

Create Model file

In this step we are going to generate the model file using terminal for we need run below command.

php artisan make:model Category

This will create the model file inside the app folder as “app/Category.php” and this file will look like below.

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Category extends Model
{
    //
}

Now update this file with same as below code.

<?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') ;

    }
}

Create Route

Add this two route into routes file named “routes/web.php“.

Route::get('category-tree-view','CategoryController@manageCategory')->name('category-tree-view');
Route::post('add-category','CategoryController@addCategory')->name('add.category');

Create Controller

In this step, we are going to create controller file for Category for that we are going run this command in terminal.

php artisan make:controller CategoryController

This will create the CategoryController.php file at “app/Http/Controllers” and it will look like this.

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class CategoryController extends Controller
{
    //
}

So we are going to update this above code that is in the controller file and after adding a new code this final file will look like below code.

<?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::all();

        return view('category.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.');

    }
}

Create View

Now we are going to create a view file so let’s create a category folder.

In this step, we are going to create a view file and folder so let’s create a “Category” folder first inside the “app/resources/view” folder.

In that folder, we will create two files named “categoryTreeview.blade.php” and “manageChild.blade.php” so the final directory structure would be “/var/www/html/laravel-hierarchical-category/resources/views/category/manageChild.blade.php” like this.

This view will exactly show the Laravel Unlimited Hierarchical Category Tree View structure.

categoryTreeview.blade.php

<!DOCTYPE html>

<html>

<head>

    <title>Laravel Unlimited Hierarchical Category Tree View 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.4.0/css/bootstrap.min.css" rel="stylesheet">

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

    <link href="{{ asset('css/treeview.css') }}" rel="stylesheet">

</head>

<body>

<div class="container">

    <div class="panel panel-primary">

        <div class="panel-heading">Unlimited Hierarchical Category Tree View</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('category.manageChild',['childs' => $category->childs])

                                @endif

                            </li>

                        @endforeach

                    </ul>

                </div>

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

                    <h3>Add New Category</h3>

                    <form role="form" id="category" method="POST" action="{{ route('add.category') }}" enctype="multipart/form-data">
                    @csrf

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

                        <label>Title:</label>

                        <input type="text" id="title" name="title" value="" class="form-control" placeholder="Enter Title">
                        @if ($errors->has('title'))
                            <span class="text-red" role="alert">
                                <strong>{{ $errors->first('title') }}</strong>
                            </span>
                        @endif

                    </div>


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

                        <label>Category:</label>
                        <select id="parent_id" name="parent_id" class="form-control">
                            <option value="0">Select</option>
                            @foreach($allCategories as $rows)
                                    <option value="{{ $rows->id }}">{{ $rows->title }}</option>
                            @endforeach
                        </select>

                        @if ($errors->has('parent_id'))
                            <span class="text-red" role="alert">
                                <strong>{{ $errors->first('parent_id') }}</strong>
                            </span>
                        @endif

                    </div>


                    <div class="form-group">

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

                    </div>


                    </form>


                </div>

            </div>




        </div>

    </div>

</div>

<script src="{{ asset('js/treeview.js') }}"></script>

</body>

</html>

manageChild.blade.php

<ul>

    @foreach($childs as $child)

        <li>

            {{ $child->title }}

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

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

            @endif

        </li>

    @endforeach

</ul>

Create CSS and JS File

Add css file inside “public/css” and js file inside “public/js” accordingly.

treeview.css

.tree, .tree ul {

    margin:0;

    padding:0;

    list-style:none

}

.panel-primary > .panel-heading {
    color: #fff;
    background-color: #606ec3;
    border-color: #606ec3;
}

.panel-primary {

    border-color: #606ec3;
    margin: 3%;

}
.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;

}

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); //li with children ul
            branch.prepend("<i class='indicator glyphicon " + closedClass + "'></i>");
            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();

$('#tree2').treed({openedClass:'glyphicon-folder-open', closedClass:'glyphicon-folder-close'});

$('#tree3').treed({openedClass:'glyphicon-chevron-right', closedClass:'glyphicon-chevron-down'});

You are almost done. Now you just want to run the site example as per my setup.

http://localhost/laravel-hierarchical-category/public/category-tree-view
demo

Your Laravel Unlimited Hierarchical Category Tree View is ready to use. Below is the GitHub link for code structure.

Leave a Reply

Your email address will not be published. Required fields are marked *