85

I am using angular-ui-router and nested states in my application, and I also have a navigation bar. The nav bar is hand written, and uses ui-sref-active to highlight the current state. It is a two-level navigation bar.

Now, when I am in, say Products / Categories I would like both Products (in level 1) and Categories (in level 2) to be highlighted. However, using ui-sref-active, if I am in state Products.Categories then only that state is highlighted, not Products.

Is there some way to make Products highlight in that state?

8 Answers 8

139

Instead of this-

<li ui-sref-active="active"> <a ui-sref="posts.details">Posts</a> </li> 

You can do this-

<li ng-class="{active: $state.includes('posts')}"> <a ui-sref="posts.details">Posts</a> </li> 

Currently it doesn't work. There is a discussion going on here (https://github.com/angular-ui/ui-router/pull/927) And, it will be added soon.

UPDATE:

For this to work, $state should be available in view.

angular.module('xyz').controller('AbcController', ['$scope', '$state', function($scope, $state) { $scope.$state = $state; }]); 

More Info

UPDATE [2]:

As of version 0.2.11, it works out of the box. Please check the related issue: https://github.com/angular-ui/ui-router/issues/818

Sign up to request clarification or add additional context in comments.

3 Comments

Did you make $state specifically available in the scope, like this $rootScope.$state = $state?
@jvannistelrooy Yes. Usually I don't put anything in $rootScope but this one is an exception.
Thanks for posting this answer. Worked perfectly for my usage. I ended up just mapping the include method on my controller's scope ($scope.includes = $state.includes) rather than attach the entire $state.
33

Here's an option for when you are nesting multiple states that are not hierarchically related and you don't have a controller available for the view. You can use the UI-Router filter includedByState to check your current state against any number of named states.

<a ui-sref="production.products" ng-class="{active: ('production.products' | includedByState) || ('planning.products' | includedByState) || ('production.categories' | includedByState) || ('planning.categories' | includedByState)}"> Items </a> 

TL;DR: Multiple, unrelated, named states need to apply an active class on the same link and you have no controller? Use includedByState.

3 Comments

Best solution if you are creating menu-links that don't follow hierarchy of State. Also if you are creating a parent menu-item in menu-link and don't want to create another State just for the sake of using ui-sref-active feature. I believe State are meant for laying out HTML not for use in menu-links.
Also works in 1.0.0-beta.1, useful for those menu links as stated above. i had a sidebar that ui-refs to one of 4 child states of a parent abstract state. Naming the abstract state name part only, works as expected when switching between the 4 sibling states.
You could place all this logic in a function :)
18

This is the solution:

<li class="myNonActiveStyle" ui-sref-active="myActiveStyle"> <a ui-sref="project.details">Details</a> </li> 

Edit:

The above only works for the exact route path and will not apply the activeStyle to the nested routes. This solution should work for this:

<a data-ui-sref="root.parent" data-ng-class="{ active: $state.includes('root.parent') }">Link</a> 

2 Comments

i have four links on which i want to add active class when one of them is selcted what i have to do for that.@holland
Or you could try just adding data-ng-class="{ active: $state.includes('root.parent') to each of the links? Where active is the class name.
11

Lets say the url tree is as follow:

app (for home page) -> app.products -> app.products.category

the usage:

<li ui-sref-active="active"> <a ui-sref="app.products">Products</a> </li> 

Now, when you press on the products: only the products will be active.

if you press on category: both products and category will be active.

if you want only the category to be active if you press it, you should use: ui-sref-active-eq on the products, which mean that only it will be active and not it's childs.

the proper use in app.js:

angular.module('confusionApp', ['ui.router']) .config(function($stateProvider, $urlRouterProvider) { $stateProvider // route for the home page .state('app', { url:'/', views: { ... } }) // route for the aboutus page .state('app.products', { url:'products', views: { ... } }) // route for the contactus page .state('app.products.category', { url:'category', views: { ... } }) $urlRouterProvider.otherwise('/'); }); 

1 Comment

Should be marked as right answer! Thank you, ui-sref-active-eq works perfectly!
2

So Simple, Step 1: Add a Controller for your nav bar orin your existing controller where nav bar is included add the following

app.controller('navCtrl', ['$scope', '$location', function($scope, $location) { $scope.isActive = function(destination) { return destination === $location.path(); } }]); 

Step2: In your nav bar

<li ng-class="{active: isActive('/home')}"><a ui-sref="app.home">Browse Journal</a></li> 

Thats it.

Comments

1

My code navigated from /productGroups to /productPartitions, which is the only way to access "productPartitions" view.

So I added a hidden anchor with ui-sref also set to "productPartitions" within the same list item that has ui-sref-active

<li ui-sref-active="active"> <a ui-sref="productGroups"> <i class="fa fa-magic"></i> Product groups </a> <a ui-sref="productPartitions" style="display:none;"></a> </li> 

Now the productGroups navigation button remains active when accessing either view

Comments

0

UI router. Code snippet to make your navigation bar active.

HTML

<li ui-sref-active="is-active" ui-nested><a ui-sref="course">Courses</a> </li> <li ui-sref-active="is-active" ui-nested><a ui-sref="blog">blog</a></li> 

CSS

is-active{ background-color: rgb(28,153,218); } 

Inside courseView.HTML

<button type="button" ui-sref="blog" class="btn btn-primary">Next</button> 

This button is present inside course View which navigate you to next View i.e blog. and makes your navigation bar highlighted.

find similar example, a demo angular ui-router app: https://github.com/vineetsagar7/Angualr-UI-Router

Comments

0

Here what I did to achieve the same. Parent state is "app.message" and do not declare as abstract.

Children states are "app.message.draft", "app.message.all", "app.message.sent".

My Nav Link -

<a ui-sref-active="active-menu" ui-sref="app.message">Messages</a> 

Define your children routes/links.

and update in config-

$rootScope.$on('$stateChangeSuccess', function (event, toState, toParams, fromState, fromParams) { if (toState.name === 'app.message') { event.preventDefault(); $state.go('app.message.draft'); return; } }); 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.