82
votes

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

8 Answers

138
votes

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

32
votes

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.

17
votes

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>
11
votes

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('/');
    });
2
votes

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.

0
votes

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

0
votes

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

0
votes

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;
                }
            });