Multi-level navigation using bootstrap in laravel 5 - php

I am using laravel 5 as my framework.
I have a categories table like this:
I want to make it as a bootstrap menu with multi-level if the parent_id = id
This is what I have tried so far:
<ul class="nav navbar-nav navbar-right">
<li class="dropdown">
Categories <span class="caret"></span>
<ul class="dropdown-menu" role="menu">
#foreach( $category as $cat )
#if( $cat->id === $cat->parent_id)
<ul class="dropdown-menu" role="menu">
<li class="dropdown-submenu">
<a href="{{ url( '/category', Safeurl::make( $cat->name ) ) }}" data-toggle="dropdown-toggle" aria-expanded="false">{{ $cat->name }}
<ul class="dropdown-menu" role="menu">
<li>
</li>
</ul>
</a>
</li>
</ul>
#else
<li>
{{ $cat->name }}
</li>
#endif
#endforeach
</ul>
</li>
</ul>
But this results is, I get the output as 1 below the other.
I want that if the parent_id = id, it should show the sub category next to the that particular id.
For example, in the current example, id = 6 has the parent_id = 4, that means, the bootstrap menu should show the sub-category link next to the Clothing.
UPDATE 1:
After the answer submitted, I cannot display the sub category.
Here's the code for that:
<li class="dropdown">
Categories <span class="caret"></span>
<ul class="dropdown-menu" role="menu">
#foreach( $category as $cat )
<li #if($cat->childs->count()) class="dropdown" #endif>
<a href="javascript:void(0)" #if( $cat->childs->count() ) class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false" #endif>
{{ $cat->name }}
#if( $cat->childs->count() )
<span class="caret"></span>
#endif
</a>
#if( $cat->childs->count() )
<ul class="dropdown-menu" role="menu">
#foreach( $cat->childs as $child )
<a href="{{url('/category', [Safeurl::make($cat->name), Safeurl::make($child->name)])}}">
{{ $child->name }}
</a>
#endforeach
</ul>
#endif
</li>
#endforeach
</ul>
How do I achieve this ?

One way to do this is add a relation in your model
public function childs()
{
return $this->hasMany('Category', 'parent_id', 'id');
}
In your controller select just category where parent_id==0
And in your view you can ask for children:
#foreach( $category as $cat )
<li #if($cat->childs->count()) class="dropdown" #endif>
</span> #endif
#if($cat->childs->count())
<ul class="dropdown-menu" role="menu">
#foreach($cat->childs as $child)
<li></li>
#endforeach
</ul>
#endif
</li>
#endforeach

Related

Displays categories and sub categories (Laravel Blade)

i have problem with display category and subcategories , i made this
in my blade
<div class="collapse navbar-collapse">
<ul class="nav navbar-nav">
<li class="active"><b class="fa fa-home"></b> Начало</li>
#foreach ($categories as $cat)
#foreach($subcategories as $sub)
#if($sub->parent_id == $cat->id)
<li class="dropdown ">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
{{$cat->name}} <i class="fa fa-caret-down"></i>
</a>
<ul class="dropdown-menu">
<li>{{ $sub->name }}</li>
</ul>
</li>
#endif
#endforeach
#endforeach
</ul>
</div>
</div>
</nav>
It show categories only when have one subcategory, i don't know why happend! Someone help me! (No bad votes please)
Here is my variables:
$categories = Category::where('parent_id', NULL)->get();
$subcategories = Category::where('parent_id','!=',NULL)->get();
The issue here is that you only create the list item within your foreach loop when there is a sub category aswell.
This example should do the trick for you.
<div class="collapse navbar-collapse">
<ul class="nav navbar-nav">
<li class="active"><b class="fa fa-home"></b> Начало</li>
#foreach ($categories as $cat)
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
{{$cat->name}} <i class="fa fa-caret-down"></i>
</a>
#foreach($subcategories as $sub)
#if($sub->parent_id == $cat->id)
<ul class="dropdown-menu">
<li>{{ $sub->name }}</li>
</ul>
#endif
#endforeach
</li>
#endforeach
</ul>
</div>
It is untested so let me know if it doesn't work.
I fixed it with little changes, but now work thanks #answered26
Here is my changes
<div class="collapse navbar-collapse">
<ul class="nav navbar-nav">
<li class="active"><b class="fa fa-home"></b> Начало</li>
#foreach ($categories as $cat)
<li class="{{ $cat->children->count() > 0 ? 'dropdown' : ''}}">
<a href="#" class="{{ $cat->children->count() > 0 ? 'dropdown-toggle' : '' }}" data-toggle="dropdown">
{{$cat->name}} {!! $cat->children->count() > 0 ? '<b class="fa fa-caret-down"></b>' : '' !!}
</a>
<ul class="dropdown-menu">
#foreach($subcategories as $sub)
#if($sub->parent_id == $cat->id)
<li>{{ $sub->name }}</li>
#endif
#endforeach
</ul>
</li>
#endforeach
</ul>
</div>
</div>

Laravel 5.4 auth::check() false

I want to make my index page with both guest and auth functions.
When guests visit, they could try logging in; And after login, it will show the user's info such as username.
Route routes/web.php:
Route::get('vendor', function () {
return view('vendor.home');
})->name('vendor')->middleware('web');
in blade template i use Auth::check() to authentication but failed.if i use middleware(['web','auth:vendor']) if guest will redirect to login page
#if(Auth::guest())
<li> <strong><i class="fa fa-user"></i> Login </strong> </li>
<li> <strong>Register</strong> </li>
#else
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false">
{{ Auth::user()->name }} <span class="caret"></span>
</a>
<ul class="dropdown-menu" role="menu">
<li>
Log Out
</li>
</ul>
</li>
#endif
{{ dd(Auth::check()) }}
Every time I logged in successfully, it will still show login button instead of user name button, after I REFRESH the index page.
this result
try replace Auth:: with \Auth:: or auth()
#if(\Auth::guest())
<li> <strong><i class="fa fa-user"></i> Login </strong> </li>
<li> <strong>Register</strong> </li>
#else
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false">
{{ \Auth::user()->name }} <span class="caret"></span>
</a>
<ul class="dropdown-menu" role="menu">
<li>
Log Out
</li>
</ul>
</li>
#endif
{{ dd(\Auth::user()) }}
This my answer
#if(Auth::guard('vendor')->check())
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false">
{{ Auth::guard('vendor')->user()->name }} <span class="caret"></span>
</a>
<ul class="dropdown-menu" role="menu">
<li>
Dashboard
</li>
<li>
<a href="{{ route('vendor.logout') }}" >Log Out</a>
</li>
</ul>
</li>
#else
<li> <strong><i class="fa fa-lock"></i> Login </strong> </li>
<li> <strong>Register</strong> </li>
#endif

Remove empty ul's in blade template foreach

I have foreach loops in my blade where I show categories and sub-categories. This is the part from the blade
<div id="sidebar">
<h1>Categories</h1>
<ul class="nav nav-stacked cat-nav">
#foreach($menu as $category_menu)
#if($menu->has('subcategories'))
<li>
{{ $menu['category_name'] }}
<ul>
#if($menu->subcategories->count())
#foreach($menu->subcategories as $subcategory)
#if($subcategory->products->count())
<li>{{$subcategory->sub_cat_name}}</li>
#endif
#endforeach
#endif
</ul>
</li>
#else
<li><i class="fa fa-link"></i> <span>{{ $menu->category_name }}</span></li>
#endif
#endforeach
</ul>
</div>
This create folowing html
<ul class="nav nav-stacked cat-nav">
<li>
Category_1
<ul>
<li>
Sub Category in Category_1
</li>
</ul>
</li>
<li>
Category_2
<ul>
</ul>
</li>
</ul>
You can see the empty ul under Category_2 because Category_2 doesn't have any assigned sub-categories to it the ul element is empty. Maybe is easy fix but I've tried to play around with loops but can't fix it.
You have to move ul under if condition like:
#if($menu->subcategories->count())
<ul>
#foreach($menu->subcategories as $subcategory)
#if($subcategory->products->count())
<li>{{$subcategory->sub_cat_name}}</li>
#endif
#endforeach
</ul>
#endif
So that ul is generated when there is some data exist for it.
Edit: If still this is not working then change the condition from
$menu->subcategories->count()
to
count($menu->subcategories) > 0
You have to put <ul> inside #if($subcategory->products->count()) with a condition if it is already declared or not to prevent seperating all of the list in <ul></ul>. Then add </ul> condition after the loop.
#if($menu->subcategories->count())
#foreach($menu->subcategories as $subcategory)
<?php $ul = false; //Create a temporary variable to validate if <ul> is already declared ?>
#if($subcategory->products->count())
#if(!$ul)
<?php $ul = true; ?>
<ul>
#endif
<li>{{$subcategory->sub_cat_name}}</li>
#if($ul)
</ul> <!-- End ul here -->
#endif
#endif
#endforeach
#endif
In the controller you may add a new attribute to the $menu which will hold a boolean value whether any subcategory has products or not:
$menu->subcategoriesHaveProducts = $menu->subcategories->map(function($subcategory) use($menu) {
return !$subcategory->products->isEmpty() || $menu->subcategoriesHaveProducts;
});
After that you must change the if condition to check if the menu has any subcategory:
#foreach($menu as $category_menu)
#if($menu->has('subcategories'))
<li>
{{ $menu['category_name'] }}
#if($menu->subcategories->count() && $menu->subcategoriesHaveProducts)
<ul>
#foreach($menu->subcategories as $subcategory)
#if($subcategory->products->count())
<li>{{$subcategory->sub_cat_name}}</li>
#endif
#endforeach
</ul>
#endif
</li>
#else
<li><i class="fa fa-link"></i> <span>{{ $menu->category_name }}</span></li>
#endif
#endforeach

Laravel 5.1 customizing the paginator styling

Is there a way to customize the paginator view in Laravel 5.1.
I want to add a first and last link in addition to the out of the box previous and next links.
I want to change the previous and next links to display icons instead of text but display text for screen readers.
I want to limit the number of page links to display only 5.
Below is what I'm trying to achieve.
<ul class="pagination no-margin pull-right">
<li class="disabled">
First
</li>
<li class="disabled">
<a href="#">
<span class="sr-only">Previous</span>
<i class="fa fa-caret-left" aria-hidden="true"></i>
</a>
</li>
<li class="active">
1
</li>
<li class="">
2
</li>
<li class="">
3
</li>
<li class="">
4
</li>
<li class="">
5
</li>
<li>
<a href="#">
<span class="sr-only">Next</span>
<i class="fa fa-caret-right" aria-hidden="true"></i>
</a>
</li>
<li >
Last
</li>
</ul>
In instead of
$users->render()
use
#include('pagination', ['paginator' => $users])
create pagination.blade in views directory
add this code in pagination file
#if ($paginator->lastPage() > 1)
<ul class="pagination">
<li class="{{ ($paginator->currentPage() == 1) ? ' disabled' : '' }}">
Previous
</li>
#for ($i = 1; $i <= $paginator->lastPage(); $i++)
<li class="{{ ($paginator->currentPage() == $i) ? ' active' : '' }}">
{{ $i }}
</li>
#endfor
<li class="{{ ($paginator->currentPage() == $paginator->lastPage()) ? ' disabled' : '' }}">
<a href="{{ $paginator->url($paginator->currentPage()+1) }}" >Next</a>
</li>
</ul>
#endif
you can add your style in this file
get the last page $paginator->lastPage() and first page is 1
You can modify this file for customizing the paginator styling
\vendor\laravel\framework\src\Illuminate\Pagination\BootstrapThreePresenter.php

Categories not showing as desired, what's wrong?

I have categories like this:
I want to create a drop down menu for the categories, which I have successfully created. But the problem is that the child category is also shown as parent category whenever I click on the link.
See the below image:
I want Western category should appear only when Apparels category is clicked (which works perfectly fine) and it should not appear when clicked on the Categories link.
Category Model:
protected $fillable = [
'name', 'parent_id'
];
public function products()
{
return $this->belongsToMany('App\Product')->withTimestamps();
}
public function childs()
{
return $this->hasMany('App\Category', 'parent_id', 'id');
}
In Contoller:
$category = Category::where('parent_id', '!=', '0')->with('childs')->get();
The view:
<li class="dropdown">
Categories <span class="caret"></span>
<ul class="dropdown-menu multi-level" role="menu">
#foreach( $category as $cat )
<li #if($cat->childs->count()) class="dropdown-submenu" #endif>
<a class="links-titilium" href="{{ url( '/store/category', [$cat->id, Safeurl::make($cat->name)] ) }}" #if( $cat->childs->count() ) class="dropdown-toggle" data-toggle="dropdown" #endif>
{{ $cat->name }}
</a>
#if( $cat->childs->count() )
<ul class="dropdown-menu" role="menu">
<li>
#foreach( $cat->childs as $child )
<a href="{{url('/category', [Safeurl::make($cat->name), Safeurl::make($child->name)])}}">
{{ $child->name }}
</a>
#endforeach
</li>
</ul>
#endif
</li>
#endforeach
</ul>
</li>
$category = Category::where('parent_id', '!=', '0')->with('childs')->get();
as per your table rows above line will fetch all the categories. To fetch the categories with level 1 try the below line.
$category = Category::where('parent_id', '1')->with('childs')->get();
- Apparels
- Clothes
-- Western
or to fetch the top level categories with child categories
$category = Category::where('parent_id', null)->with('childs')->get();
- None
- Apparels
- Clothes
-- Western
I would try to make a condition right after the first foreach loop. It has to englobe the whole li so that it does not create the element if the array is at a child's index.
#foreach( $category as $cat )
#if($cat->parent_id == 1) /*this is the beginning of the if statement*/
<li #if($cat->childs->count()) class="dropdown-submenu" #endif>
<a class="links-titilium" href="{{ url( '/store/category', [$cat->id, Safeurl::make($cat->name)] ) }}" #if( $cat->childs->count() ) class="dropdown-toggle" data-toggle="dropdown" #endif>
{{ $cat->name }}
</a>
#if( $cat->childs->count() )
<ul class="dropdown-menu" role="menu">
<li>
#foreach( $cat->childs as $child )
<a href="{{url('/category', [Safeurl::make($cat->name), Safeurl::make($child->name)])}}">
{{ $child->name }}
</a>
#endforeach
</li>
</ul>
#endif
</li>
#endif /*this is the end of the if statement*/
#endforeach`

Categories