I am a little bit new with laravel 5.1 framework. Last couple of days I create my database (insert, update, delete) for dynamic menu I want to create. I connect with default layout in which i put menu. From route code looks like this.
View::composer('layouts.default',function($view){
$menus = Menu::where('parent_id',0)->orderBy('order')->get();
$submenus = Menu::where('parent_id','!=',0)->get();
$view->with(compact('menus','submenus'));
});
In main menu are items with parent_id = 0. Submenu items have parent_id = id, and soo on.
I want to display correct but when I hover main menu items that dont have items, css block appear, becouse i didnt make good if condition. Is there any way to do this?
Code in view look like this.
#foreach($menus as $menu)
<li class="dropdown {!! (Request::is('typography') || Request::is('advancedfeatures') || Request::is('grid') ? 'active' : '') !!}"> {!! $menu->title !!}
<ul class="dropdown-menu" role="menu">
#foreach($submenus as $submenu)
#if($submenu->parent_id === $menu->id)
<li>{!! $submenu->title !!}
#foreach($submenus as $smenu)
#if($smenu->parent_id === $submenu->id)
<ul class="dropdown-submenu" role="menu">
<li>{!! $smenu->title !!}
</li>
</ul>
#endif
#endforeach
</li>
#endif
#endforeach
</ul>
</li>
#endforeach
One more question is how to take only one value from Menu model for example id that can be used to point only one submenu.
Best regards!
You can do it simply by using recursion. I removed html classes for readability.
Note: Set NULL parent_id for root items.
Add this relation to your Menu Model.
function childs()
{
return $this->hasMany('Namespace\Menu','parent_id', 'id');
}
In your controller get the menus who has no parent.
$menus = Menu::whereNull('parent_id')->orderBy('order')->get();
Then display them in your view.
<ul>
#foreach($menus as $menu)
<li>
{!! $menu->title !!}
#include('childItems')//recursion view
</li>
#endforeach
</ul>
And this is what your childItems.blade.php will look like.
<ul>
#foreach($menu->childs as $menu)
<li>
{!! $menu->title !!}
#include('childItems')//call itself for deeper relations.
</li>
#endforeach
</ul>
That's it.
Related
I have a menu and in this menu items come from Categories
For the test, I create a new section called Menu for this menu to create the menu manually.
But after that, I return all codes to the previous version, But still, I have an error for undefined $menus
But I don't have this menu anywhere, where is the problem?
Error
Undefined variable $menus (View:
C:\Web\projects\thermotajhiz\resources\views\layouts\header.blade.php)
View
<ul class="list-menu-level-2">
#foreach($categories as $category)
#if($category->menu == 1)
<li class="item-menu-2">
<a href="#" class="list-category-menu-2" rel="nofollow">
<i class="fa fa-desktop"></i>
{{ $category->name }}
</a>
<ul class="megamenu-level-3" style="display:block;">
#include('layouts.categories-group',['categories' => $category-
>get_sub($category->id)])
</ul>
</li>
#endif
#endforeach
</ul>
Controller
$categories = Category::with('child')->where('parent_id', 0)->get();
return view('index', compact('categories'));
Please run a command php artisan view:clear, because laravel makes a cache for every view file. after runnig this command, all compiled views should clear and rebuild cache for view for present file.
i want to create a sub menu on my templates/master. i want all my process in there. i have table: menu, role, and menu_role (conatins many to many from menu and role).
i tried to select table menu through menu_role, because i want display menu according to its role. it success but there is no sub menu. i'm bad at query builder with relationship.
this is my templates/master.blade.php :
use App\MenuRole;
use App\Role;
use App\Menu;
use App\Admin;
use App\Operator;
$userCheck = Auth::user()->role_id;
$menus = MenuRole::with('menu')->where('role_id', $userCheck)->get();
and for the html, if there is no module on table menu i want to display this :
#foreach($menus as $menu)
<li>{{ $menu->menu->title }}</li>
#endforeach
and if there is a module, i want to display this :
<li class="has-sub">
<a class="js-arrow" href="#">
<i class="fas fa-tachometer-alt"></i>{{ $menu->module }}</a>
<ul class="navbar-mobile-sub__list list-unstyled js-sub-list">
<li>{{ $menu->menu->title }}</li>
</ul>
</li>
so the thing is, in table menu i have field module. this field will distinguish which ones have subMenu and which have no subMenu. and i want to foreach table menu. i have configure the model.
Will a simple #empty condition suffice? When a Menu has the module field filled it shows one thing, otherwise the other.
#foreach ($menus as $menu)
#empty($menu->menu->module)
#else
#endempty
#endforeach
If this does not solve your problem, could you please go into more detail about what you want it to look like?
Here I want to make one submenu active out of four submenu. This is for dynamic slug .
<div class="solution_tabs">
#foreach($allMenu as $menu)
<ul class="submenu">
#if(isset($menu->submenus))
#foreach($menu->submenus as $submenu)
#if(isset($submenu->page->slug))
<li class="active">{{ $submenu->name}}</li>
#else
<li>{{ $submenu->name}}</li>
#endif
#endforeach
#endif
</ul>
#endforeach
</div>
same as this image,i want one active submenu from dynamic submeun of the menu
You should compare the current URL with your link URLs in order to detect coincidences. One way to accomplish it could be injecting request in your blade file, using
#inject('request', 'Illuminate\Http\Request')
and then check for matches like this:
<li class="{{ $request->segment(1) == $submenu->page->slug ? 'active' : '' }}">{{ $submenu->name}}</li>
Please note that segment() is 0 based, so segment(1) works when your url is like example.com/segment(0)/page->slug
I have a services list. Now I want to add sub-services to services list. I have two tables 'services' and 'sub-services' with foreign key constraint 'service_id'. Now, I want to show the 'services' and related 'sub-services' in master.blade.php. For services it was working fine, but, when trying with sub-services then getting this error. Would someone please help to get the expected result.
In master.blade.php-
<li class="dropdown"> Services
<ul class="dropdown-menu services-dropdown" role="menu">
#forelse(App\Model\Service::all() as $service)
<li class="dropdown-submenu">
{{ $service->title }}
<ul class="dropdown-menu sub-services">
#foreach(App\Model\SubService::where('service_id', '=',$service->id)->get()) as $subservice)
<li>
{{ $subservice->title }}
</li>
#endforeach
</ul>
</li>
#empty
#endforelse
</ul>
</li>
Two tables are here-
1.Services table
2.Sub-services table
You're using the wrong syntax. You're using redundant ) near the get(), so change it to:
#foreach(App\Model\SubService::where('service_id', $service->id)->get() as $subservice)
Also, as I say in my best practices repo, you shouldn't execute queries in a Blade template. Consider moving the logic to a controller.
This error also occurs when you don't close you loop correctly.
Use #foreach() to start a loop and #endforeach to close the same loop.
Its a bad way to write a logic part in blade file.I would suggest you to move it to controller because if in case you need to change the code you have to edit blade page.As well as please make use of relationship for fetching the data you can relate your Service with SubService
E.g
Service.php (model file)
public function subServices()
{
return $this->hasMany('App\SubService');
}
SubService.php (model file)
public function services()
{
return $this->belongsTo('App\Service','service_id');
}
your blade code:
#forelse(App\Model\Service::all() as $service)
<li class="dropdown-submenu">
{{ $service->title }}
<ul class="dropdown-menu sub-services">
#foreach($service->subServices as $subservice)
<li>
{{ $subservice->title }}
</li>
#endforeach
</ul>
</li>
#empty
#endforelse
I have 2 models 'Trips.php'
public function region()
{
return $this->belongsTo('App\Region');
}
Region.php
public function trips()
{
return $this->hasMany('App\Trip');
}
I'm trying to show the trips that are in one one specific region. For example: I have a region named Lake Side and I want to show all trips that are in Lake Side region in list.
I tried the following:
In controller:
$trips = Trip::all();
In view:
#foreach($trips as $trip)
<li><a href="#">
{{$trip->region->name}}</a>
<ul class="dropdown">
<li><a href="#">
{{$trip->title}}</a>
</li>
</ul>
</li>
#endforeach
This gives me region name and trip name but repeats region name if more than one trip is made in same region.
And tried another way around (inverse):
<ul class="dropdown">
#foreach($regions as $region)
<li><a href="#">
{{$region->tour->title}}</a>
</li>
#endforeach
</ul>
And getting error Trying to get property of non-object
One way to do that is to use whereHas():
$trips = Trip::whereHas('region', function($q) use ($regionName) {
$q->where('name', $regionName);
})->get();
Pass $trips and $regionName to the view:
#foreach ($trips as $trip)
<li>{{ $regionName }}
<ul class="dropdown">
<li><a href="#">
{{ $trip->title }}</a>
</li>
</ul>
</li>
#endforeach
Alternatively, you can use eager loading:
$region = Region::where('name', $regionName)->with('trips')->first();
And in the view:
#foreach ($region->trips as $trip)
<li>{{ $region->name }}
<ul class="dropdown">
<li><a href="#">
{{ $trip->title }}</a>
</li>
</ul>
</li>
#endforeach
By getting trips with regions, what you're essentially getting is every trip with a region property.
Instead do the reverse Region::with('trips')->where('id', $regionId)->get() and you'll get regions with their trips. So now every region result has a trips property which contains many trips.
Alternatively don't use eager load. So Region::firstOrFail($regionId) then just use $region->trips.
And you can loop through them like
// Can print region here
#foreach($region->trips as $trip)
// Can print region's trips here
#endforeach