Mehdi Jalali
Mehdi Jalali

Reputation: 23

multi level subcategory in laravel

i want to show categories list on selectbox with tree structure (multi level subcategory)
similar this:

-electronic
  --camera
    ---sumsung
       ---- other subcategory
       ---- ...
    ---lg
-art

table structure:

+----+------------+-----------+
| id | name       | parent_id |
+----+------------+-----------+
| 1  | electronic | 0         |
+----+------------+-----------+
| 2  | arts       | 0         |
+----+------------+-----------+
| 3  | camera     | 1         |
+----+------------+-----------+
| 4  | sumsung    | 3         |
+----+------------+-----------+
| 4  | lg         | 3         |
+----+------------+-----------+

Category model:

public function children()
{
    return $this->hasMany(self::class, 'parent_id', 'id');
}

public function parent()
{
    return $this->belongsTo(self::class, 'parent_id');

}

and this return only category and 1 level subcategories

<select>
    @foreach($data as $categories)
        <optgroup label="{{ $categories->name }}">
            @foreach($categories->children as $category)
                <option value="{{ $category->id }}">{{ $category->name }}</option>
            @endforeach
        </optgroup>
    @endforeach
</select>

how to show multi level subcategory?

Upvotes: 2

Views: 6374

Answers (1)

Ahmad Karimi
Ahmad Karimi

Reputation: 1383

Well, here I didn't followed your approach by putting the categories in a select box, but instead I have chosen to depict it via nested unordered lists, but you can find a way to make it work for you in select box too.

To tackle multilevel category rendering, you can use a recursive approach. Here, I have created a blade template file namely categories.blade.php the code is as below:

categories.blade.php

<!-- Displaying the current category -->
<li value="{{ $category->id }}">{{ $category->name}}

    <!-- If category has children -->
    @if (count($category->children) > 0)

        <!-- Create a nested unordered list -->
        <ul>

            <!-- Loop through this category's children -->
            @foreach ($category->children as $sub)

                <!-- Call this blade file again (recursive) and pass the current subcategory to it -->
                @include('subcategories', ['category' => $sub])
        
            @endforeach
        </ul>
    @endif
</li>

Now, in your parent blade template file, you can include the categories.blade.php file in a way to loop through your categories and display them.

... 

<!-- Start an unoredered list -->
<ul>

    <!-- Loop through each category -->
    @foreach ($categories as $category)

        <!-- Include subcategories.blade.php file and pass the current category to it -->
        @include('subcategories', ['category' => $category])
    @endforeach
<ul>

... 

Here is an example that worked for me using the above technique: enter image description here

Note 1: based on my example, the categories.blade.php file and the parent blade file are assumed to be in the same folder, if you decide to put them in different folder, make sure to put the correct path in the @include statement in the parent blade file.

Note 2: As per this: https://www.w3.org/TR/html401/interact/forms.html#h-17.6, you cannot put nested optgroup tags inside one another, so I suggest you find another way to display your select box.

Upvotes: 2

Related Questions