Laravel Why my drop down menu is showing all elements when hovered? - php

In my navbar I am showing the parent items. Which I am getting by using getItems() method. It is being linked to every item. And every parent item has some child items. Which I am getting using ($item->children as $child) And when one hovers over any parent item, the child items of that parent item should be visible from drop down.
The problem is whenever I hover around any item, every child item is being shown in the drop down. But I want only the child item of the parent item to be shown. The problem is likely with my #foreach loops. But I am not getting where. It would be nice If someone can help me out. Thanks in advance.
This is my blade file code.
<div class="navbar-list">
<div class="dropdown">
#foreach(getItems() as $item)
{{ $item->name }}
<div class="dropdown-menu">
#foreach ($item->children as $child)
<li class="dropdown-item" data-id="{{ $child->id }}" data-name="{{ $child->name }}">
<span>{{ $child->name }}</span>
</li>
#endforeach
</div>
#endforeach
</div>
</div>
And here is it's style
<style>
.dropdown:hover>.dropdown-menu {
display: block;
}
.dropdown>.dropdown-toggle:active {
pointer-events: none;
}
</style>

Every item in your first #foreach needs to be its own dropdown. Place <div class="dropdown"> inside your loop:
<div class="navbar-list">
#foreach(getItems() as $item)
<div class="dropdown">
{{ $item->name }}
<div class="dropdown-menu">
#foreach ($item->children as $child)
<li class="dropdown-item" data-id="{{ $child->id }}" data-name="{{ $child->name }}">
<span>{{ $child->name }}</span>
</li>
#endforeach
</div>
</div>
#endforeach
</div>

Related

How to create url form in menu dynamic laravel

I just want to know how create condition in laravel if url field / form in menus is true then in menu href will linked into $url, unless if url form is null, then in menu href will linked into $id just as usual.
my blade menu child :
<ul>
#foreach ($childs as $child)
<li>#if (count($child->childs)) #endif</li>
<li class="dropdown">
{{$child->nama}}#if (count($child->childs)) #endif
#if (count($child->childs))
#include('menuChild', ['childs'=> $child->childs])
#endif
</li>
#endforeach
</ul>
Try to change your code into this
<ul>
#foreach ($childs as $child)
<li><a #if (request($child->link, true))href="{{$child->link}}"#endif></a></li>
{{-- <li> #if (count($child->childs)) #endif</li> --}}
<li class="dropdown">
{{$child->nama}}#if (count($child->childs)) #endif
{{-- <li class="dropdown">#if (count($child->childs)) #endif --}}
#if (count($child->childs))
#include('menuChild', ['childs'=> $child->childs])
#endif
{{-- </li> --}}
</li>
#endforeach
</ul>

Laravel Bootstrap Accordion is not working properly?

In my accordion I am showing the parent items. Which I am getting by using getItems() method. It is being linked to every item. And every parent item has some child items. Which I am getting using ($item->children as $child) And when clicks any parent item, the child items of that parent item should be visible from drop down.
The problem is whenever I click any parent item, every child item is being shown in the drop down. But I want only the child item of the parent item to be shown. It would be nice If someone can help me out. Thanks in advance.
This is my blade file code.
<div class="container my-4">
<div class="accordion md-accordion" id="accordionEx" role="tablist" aria-multiselectable="true">
<div class="card">
<div class="card-header" role="tab" id="headingTwo2">
#foreach(getItems() as $item)
<a class="collapsed" data-toggle="collapse" data-parent="#accordionEx" href="#collapseTwo2"
aria-expanded="false" aria-controls="collapseTwo2">
<h5 class="mb-0">
{{ $item->name }} <i class="fas fa-angle-down rotate-icon"></i>
</h5>
</a>
<div id="collapseTwo2" class="collapse" role="tabpanel" aria-labelledby="headingTwo2"
data-parent="#accordionEx">
<div class="card-body">
#foreach ($item->children as $child)
<a href="{{ route('category.island.list') }}?category={{ $child->id }}"
class="dropdown-item" data-id="{{ $child->id }}" data-name="{{ $child->name }}">
<span>{{ $child->name }}</span>
</a>
#endforeach
</div>
</div>
#endforeach
</div>
</div>
</div>
</div>
This is normal, because they all have the same href here:
<a class="collapsed" data-toggle="collapse" data-parent="#accordionEx" href="#collapseTwo2"
aria-expanded="false" aria-controls="collapseTwo2">
and they all have make reference to the same "id" in this div:
<div id="collapseTwo2" class="collapse" role="tabpanel" aria-labelledby="headingTwo2"
data-parent="#accordionEx">
So just add a variable in your foreach as a "count" that will increase foreach loop and you just add that into your href and Id with twig and that is fine :)
Twig way:
Out of 1st foreach : TWIG : {% set count = 0 %} PHP : <?php $count = 0; ?>
In your 1st foreach at the end: TWIG : {% set count = count + 1 %} PHP : <?php $a++; ?>
As follow:
<div class="container my-4">
<div class="accordion md-accordion" id="accordionEx" role="tablist" aria-multiselectable="true">
<div class="card">
<div class="card-header" role="tab" id="headingTwo2">
<?php $count = 0; ?>
#foreach(getItems() as $item)
<a class="collapsed" data-toggle="collapse" data-parent="#accordionEx" href="#collapseTwo2{{ $count }}"
aria-expanded="false" aria-controls="collapseTwo2{{ $count }}">
<h5 class="mb-0">
{{ $item->name }} <i class="fas fa-angle-down rotate-icon"></i>
</h5>
</a>
<div id="collapseTwo2{{ $count }}" class="collapse" role="tabpanel" aria-labelledby="headingTwo2"
data-parent="#accordionEx">
<div class="card-body">
#foreach ($item->children as $child)
<a href="{{ route('category.island.list') }}?category={{ $child->id }}"
class="dropdown-item" data-id="{{ $child->id }}" data-name="{{ $child->name }}">
<span>{{ $child->name }}</span>
</a>
#endforeach
</div>
</div>
<?php $count++; ?>
#endforeach
</div>
</div>
</div>
</div>

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

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`

Multi-level navigation using bootstrap in laravel 5

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

Categories