How to set active menu based on current route? - php

Can anyone suggest a good way of setting the active class on the correct navbar menu item (e.g. in Bootstrap) based on what the current-handled fat-free route is?
The navbar menu in my main template looks like this:
<ul class="nav navbar-nav">
<li class="active">Home</li>
<li>Data
<li>About</li>
</ul>
I could put a check-if around each of these, something like:
<ul class="nav navbar-nav">
<li>{{ #route }}</li>
<li <check if="{{ #route == '/' }}"> class="active"</check>>Home</li>
<li <check if="{{ #route == '/data' }}"> class="active"</check>>Data
<li <check if="{{ #route == '/about' }}"> class="active"</check>>About</li>
</ul>
But that means both setting the #route variable in every route ($f3->set('route', $f3->get('PARAMS.0'))), and embedding the check and the route to compare it to in the template seems prone to error when making changes. I'd quite like to have the link appear active if the start of the route matches (e.g. still set the Data link as active if the route is /data/set/5/report), which would add to the complexity of the template.
I'm partially considering putting all the data for the menu inside an associative array in the code and generating the menu in the template, but I don't like the idea of taking the design of the menu out of the template and into the code.
Any ideas or discussion fully welcomed!

Well it depends partially on how you've defined your routes.
If your routes look like GET /#controller/#action, then the following should do the trick:
{~ $links=array(''=>'Home','data'=>'Data','about'=>'About') ~}
<ul>
<repeat group="#links" key="#ctrl" value="#label">
<li class="{{ #ctrl==##PARAMS.controller ? 'active' : '' }}">
{{ #label }}
</li>
</repeat>
</ul>
(Notice the double ## not to choke on homepage).
If your routes are defined one by one (GET /, GET /data, etc...), then you need to refine a bit the active state detection:
{~ $links=array('/'=>'Home','/data'=>'Data','/about'=>'About') ~}
<ul>
<repeat group="#links" key="#uri" value="#label">
<li class="{{ (#uri=='/' ? #PATH==#uri : strpos(#PATH,#uri)===0) ? 'active' : '' }}">
{{ #label }}
</li>
</repeat>
</ul>
If your routes are defined one by one and named appropriately (GET #home: /, GET #data: /data, GET #data_foo: /data/foo, etc...), then you can avoid hardcoding URIs inside templates:
{~ $links=array('home'=>'Home','data'=>'Data','about'=>'About') ~}
<ul>
<repeat group="#links" key="#name" value="#label">
<li class="{{ strpos(#ALIAS,#name)===0 ? 'active' : '' }}">
{{ #label }}
</li>
</repeat>
</ul>
Whichever method you choose, you may consider defining $links in a config file to improve maintainability.

Related

Laravel Question: Is that possible to temporary disable url in route without remove?

Let say below this example:-
<li class="menu">About
<ul>
<li>--></li>
</ul>
</li>
Is that possible make this to disable? like or // ?? Any Ideas?
In blade file you can comment codes with {{-- your code --}}
{{-- <li>--></li> --}}
You can use a URL helper In laravel to disable
<li><a href='{!! route('HERE'); !!}'>--></a></li>
reference

Laravel Blade If Statement throwing Non-Object Property Error upon Auth Check with Guard

I'm VERY new to laravel, so I'm honestly not sure what information to provide but I'll try to the best of my ability to ask the question throughly.
Lets take a look at my code:
#if(Auth::guard('admin')->check() || Auth::guard('web')->check())
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false">
{{ Auth::user()->name }} <span class="caret"></span>
</a>
{{-- Authenticated Dropdown Menu --}}
<ul class="dropdown-menu" role="menu">
{{-- Admin Links --}}
#if (Auth::guard('admin')->check())
<li>Manage Blog Posts</li>
<li role="separator" class="divider"></li>
#endif
{{-- User Links --}}
#if (Auth::guard('web')->check() || Auth::guard('admin')->check())
<li>User Test Link</li>
<li role="separator" class="divider"></li>
#endif
{{-- Logout and Form --}}
<li>
<a href="{{ route('logout') }}"
onclick="event.preventDefault();
document.getElementById('logout-form').submit();">
Logout
</a>
{!! Form::open(['route' => 'logout', 'id' => 'logout-form', 'style' => 'display: none;']) !!}
{!! Form::close() !!}
</li>
{{-- End Logout Form --}}
</ul>
</li>
#else
<li>Login</li>
<li>Register</li>
#endif
Now I thought that Auth::guard('admin')->check() returned true or false depending on if the user has authentication or not. I also need to run this if statement against two guards, and checking if the admin is logged in OR the user is logged in.
Basically, as you can probably tell from my code, i want the bootstrap dropdown to display if logged in, if not then display login and register buttons.
THEN If the User is logged in the dropdown won't show the "Manage Blog Posts" link because thats an Admin link... If an Admin is logged in however then display both links.
As you can see in this snippet below, this is the SAME EXACT if statement as the very top. This one works just fine, but the parent if statement doesn't want to seem to work.
{{-- User Links --}}
#if (Auth::guard('web')->check() || Auth::guard('admin')->check())
<li>User Test Link</li>
<li role="separator" class="divider"></li>
#endif
This error only seems to happen when I'm logged in as an admin ONLY and I try to visit any page thats not protected by my auth:admin middleware.
Am I getting this error because I'm nesting my if statements incorrectly? Maybe I'm just tired and need a second set of eyes to see the smallest error. I've followed DevMarketers Multi Auth tutorial on YouTube to help set this up.
(DevMarketer's YouTube Multi-Auth Tutorial: https://youtu.be/iKRLrJXNN4M?list=PLwAKR305CRO9S6KVHMJYqZpjPzGPWuQ7Q)
Attached is a screenshot of the error message(s) I'm getting as well as a pastebin for the entire _nav.blade.php. This view is a partial. I did also just run composer update before i started working and noticed that the laravel framework just went from 5.4.32 to 5.4.33. Don't know if that would make a dramatic difference or not.
https://pastebin.com/pLDTmU4w
http://imgur.com/a/0y6kd
I can provide my github repo link for this project upon request.
Because you are using the admin guard you need to retrieve the user from that. Try this on line 38:
{{ Auth::guard('admin')->user()->name }}
or you could check if admin
{{ Auth::guard('admin')->check() ? Auth::guard('admin')->user()->name : Auth::user()->name }}

PyroCMS theme custom navigation structure

I've searched everywhere but can't seem to find anything in the documentation or anywhere else. I've created my own custom theme, copypasting stuff from the Starter theme which ships with PyroCMS. In my navigation partial there is this twig directive:
{{ structure()
.linkAttributesDropdown({'data-toggle': 'dropdown'})
.listClass('nav navbar-nav navbar-right')
.childListClass('dropdown-menu')
.render()|raw }}
This works when using the Bootstrap framework. I am using Purecss.io and I want to assign different classes and assign classes to more elements. My navigation should look like this:
<ul class="pure-menu-list">
<li class="pure-menu-item pure-menu-selected">
<a href="http://local.dev" class="pure-menu-link" >Home</a>
</li>
<li class="pure-menu-item pure-menu-has-children pure-menu-allow-hover">
Item with children
<ul class="pure-menu-children">
<li class="pure-menu-item">
Child 1
</li>
<li class="pure-menu-item">
Child 2
</li>
</ul>
</li>
</ul>
I've tried the folling in my partial:
{{ structure()
.linkAttributesDropdown({'class': 'pure-menu-item pure-menu-has-children pure-menu-allow-hover'})
.listClass('pure-menu-list')
.elementClass('pure-menu-item')
.childListClass('pure-menu-children')
.render() }}
But that doesn't do the trick.
How would I accomplish this? Where can I find documentation for the used functions structure(), listClass() etc.?
Thanks in advance!
Unfortunately this portion of the system is still being developed but I can show you the macro and how to interact with it:
https://github.com/anomalylabs/pages-module/blob/master/resources/views/macro.twig
The chaining you are seeing is how you set the options so structure().fooBar(value) set's the foo_bar option to value in the options collection.
For elementClass you are probably looking for linkClass. Also don't forget to escape with |raw!
Looks like this will give you your desired markup:
{{ structure()
.currentClass('pure-menu-selected')
.dropdownClass('pure-menu-has-children pure-menu-allow-hover')
.linkAttributesDropdown({'class': 'pure-menu-item pure-menu-has-children pure-menu-allow-hover'})
.listClass('pure-menu-list')
.itemClass('pure-menu-item')
.linkClass('pure-menu-link')
.childListClass('pure-menu-children')
.render()|raw }}
Here's some information:
The very basic default looks like the following and will create an unordered list with all your existing pages. If you have set/toggled a page to be NOT enabled, then it will not show up.
{{ structure()|raw }}
Change the class of the list element
{{ structure().list_class('navigation')|raw }}
Change the list tag to something else than unordered list:
{{ structure().list_tag('dl')|raw }}
Change list element
{{ structure().link_tag('dt')|raw }}
Show children of only a specific page
{{ structure().root('/my-page')|raw }} or page-id {{ structure().root('9')|raw }}
Set class for the element with children
{{ structure().dropdown_class('has-children')|raw }}
Set a class to every li item:
{{ structure().item_class('has-children')|raw }}
Set a class to the link
{{ structure().link_class('my-class')|raw }}
Add a title attribute to the link
{{ structure().link_attributes({'title':'Title attribute'})|raw }}

Make a link active from the base.html.twig on Navbar in symfony

I researched a lot of things on stack and any other sources.
I found some interesting ideas but couldn't apply them as i'm a student and cannot just yet know where to put things directly in their right spot.
So I got this code right in the base.html.twig
<ul class="nav navbar-nav">
<li class="active">
Accueil<span class="sr-only">(current)</span>
</li>
<li>Nos livres</li>
<li>Être édité</li>
</ul>
and I would like, without using Jquery, being able to show the active when I click on a Link and going to that page.
I found that sort of code :
class="{% if app.request.attributes.get('_route') == '_list' %}active{% endif %}"
(and other things looking nearly similar)
But I really don't know how and where to put it with my own link and such.
If any help is given, this would be really appreciated, thank you :)
ps: i'm using symfony 2.8
You need to insert the code on your li's like this:
<ul class="nav navbar-nav">
<li class="{% if app.request.attributes.get('_route') == '_RouteName' %}active{% endif %}">
Accueil<span class="sr-only">(current)</span>
</li>
<li class="{% if app.request.attributes.get('_route') == '_RouteName' %}active{% endif %}">
Nos livres
</li>
<li class="{% if app.request.attributes.get('_route') == '_RouteName' %}active{% endif %}">
Être édité
</li>
</ul>
Replace _RouteName with the correct _route for each link.
I know this question has been answered but I found a neat approach for a different situation which might help somebody who has submenus, just like me:
You can search for a substring inside string in twig
{# returns true #}
{{ 'ca' in 'car' }}
What I did with my routes and navigation to make the links active
<li>
<a href="{{ url('admin_agency_index') }}"
class="{% if 'admin_agency_' in app.request.attributes.get('_route') %}active{% endif %}">
<i class="lnr lnr-apartment"></i>
<span>Agencies</span>
</a>
</li>
My agency routes are named like:
admin_agency_new
admin_agency_edit
admin_agency_delete
In that case, if you reach a submenu for adding an agency for example, you will still have active class in your html.

Determine current page in twig template and set a css class to the corresponding link

I have a Twig template with a simple fixed menu. I use the code below to determine the link that corresponds with the current page. This is far from pretty.
Is there an alternative way to determine this in Twig it self?
I prefer not to send an array from the controller to the template where the links are defined (in that way I could check for the current page in the loop and avoid - in my eyes - double code)
Is there something I oversaw in the documentation of Twig?
<ul>
<li {% if app.request.get('_route') == 'all' %}class="current"{% endif %}>
All
</li>
<li {% if app.request.get('_route') == 'second' %}class="current"{% endif %}>
Second
</li>
<li {% if app.request.get('_route') == 'third' %}class="current"{% endif %}>
Third
</li>
<li {% if app.request.get('_route') == 'fourth' %}class="current"{% endif %}>
Fourth
</li>
</ul>
I actually think this might the best way to do it - at least in terms of accessing app.request.get('_route'). The only alternative could be app.request.getUri but that feels less dynamic - that is to say, if the route's URL changed, you'd need to update your template.
You could of course store the current route in a variable that you then passed to the template, which would mean you didn't have to keep accessing app.request.get('_route'); instead you could just check against that variable each time.

Categories