damogari
damogari

Reputation: 35

How can I highlight link to current page with Angular?

I am using Angular Routing on my page and I also want to highlight menu item corresponded to current content.

I tried to use ngClass and controller like in this post but it has no effect

Here's the code:

index.html

<body ng-app="sApp">
<div ng-controller="NavCtrl" class="nav">
  <ul>
    <li ng-class="{ active-btn: isActive('/')}">
      <a href="#" class="menu-btn">HOME</a>
    </li>
    <li ng-class="{ active-btn: isActive('/1')}">
      <a href="#/1" class="menu-btn">PAGE1</a>
    </li>
    <li ng-class="{ active-btn: isActive('/2')}">
      <a href="#/2" class="menu-btn">PAGE2</a>
    </li>
  </ul>
</div>
<div class="content" ng-view=""></div>

style.css

.nav {
  padding: 1rem;
  text-align: center;
  background-color: #ffa500;
}
.nav ul li {
  display: inline;
  font-weight: 700;
}
.menu-btn {
  padding: 1rem;
}
.menu-btn:hover {
  background-color: #ee82ee;
}
.active-btn {
  background-color: #00f;
}

script.js

'use strict';
var sApp;

sApp = angular.module('sApp', ['ngRoute']);

sApp.config(function($routeProvider) {
  return $routeProvider
  .when('/', {templateUrl: 'h.html'})
  .when('/1', {templateUrl: '1.html'})
  .when('/2', {templateUrl: '2.html'})
  .otherwise({redirectTo: '/'});
});

sApp.controller('NavCtrl', function($scope, $location) {
  $scope.isActive = function(viewLocation) {
    return viewLocation === $location.path();
  };
});

Here is the plunker:

It looks like that menu items can't change the classes to active-btn. Can you help me please?

Upvotes: 3

Views: 4309

Answers (2)

kfwerf
kfwerf

Reputation: 129

<!DOCTYPE html>
<html>

  <head>
    <script data-require="angular.js@*" data-semver="1.3.0-beta.5" src="https://code.angularjs.org/1.3.0-beta.5/angular.js"></script>
    <script data-require="angular-route@*" data-semver="1.2.20" src="https://code.angularjs.org/1.2.20/angular-route.js"></script>
    <link rel="stylesheet" href="style.css" />
    <script src="script.js"></script>
  </head>

  <body ng-app="sApp">
    <div ng-controller="NavCtrl" class="nav">
      <ul>
        <li ng-class="classActive('/')">
          <a href="#" class="menu-btn">HOME</a>
        </li>
        <li ng-class="classActive('/1')">
          <a href="#/1" class="menu-btn">PAGE1</a>
        </li>
        <li ng-class="classActive('/2')">
          <a href="#/2" class="menu-btn">PAGE2</a>
        </li>
      </ul>
    </div>
    <div class="content" ng-view=""></div>
  </body>

</html>

And the script.js

 'use strict';
  var sApp;

  sApp = angular.module('sApp', ['ngRoute']);

  sApp.config(function($routeProvider) {
    return $routeProvider
    .when('/', {templateUrl: 'h.html'})
    .when('/1', {templateUrl: '1.html'})
    .when('/2', {templateUrl: '2.html'})
    .otherwise({redirectTo: '/'});
  });

  sApp.controller('NavCtrl', function($scope, $location) {
    $scope.isActive = function(viewLocation) {
      return viewLocation === $location.path();
    };

    $scope.classActive = function( viewLocation ) {
      if( $scope.isActive(viewLocation) ) {
        return 'active-btn';
      }
      else {
        return 'inactive-btn';
      }
    }
  });

Its better to not put too much logic in the html, to have a function like this makes a lot more sense. Even more sense would be to wrap all the menu stuff in a object and just iterate the object. Then you can also listen to locationsuccess for instance and just change the object, without changing it on click. That way its not dependent on a click.

Thats how i would do it, that way the logic can stay in a abstract service too and is more reusable.

Goodluck!

Upvotes: 0

You can do something like this:

   <li ng-class="{active: $route.current.loadedTemplateUrl=='/1'}">
     My 1 active
   </li>

Upvotes: 2

Related Questions