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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.