Búsqueda de sitios web

javascript - ¿Cómo establecer la clase activa de la barra de navegación de Bootstrap con Angular JS?


Si tengo una barra de navegación en Bootstrap con los elementos

Home | About | Contact

¿Cómo establezco la clase activa para cada elemento del menú cuando están activos? Es decir, ¿cómo puedo establecer class="active" cuando la ruta de Angular está en

  1. #/ para inicio
  2. #/about para la página de información
  3. #/contact para la página de contacto

Respuesta #1

Una forma muy elegante es usar ng-controller para ejecutar un solo controlador fuera del ng-view:

<div class="collapse navbar-collapse" ng-controller="HeaderController">
    <ul class="nav navbar-nav">
        <li ng-class="{ active: isActive('/')}"><a href="/">Home</a></li>
        <li ng-class="{ active: isActive('/dogs')}"><a href="/dogs">Dogs</a></li>
        <li ng-class="{ active: isActive('/cats')}"><a href="/cats">Cats</a></li>
    </ul>
</div>
<div ng-view></div>

e incluir en controllers.js:

function HeaderController($scope, $location) 
{ 
    $scope.isActive = function (viewLocation) { 
        return viewLocation === $location.path();
    };
}

Respuesta #2

Acabo de escribir una directiva para manejar esto, así que simplemente puedes añadir el atributo bs-active-link al elemento padre <ul>, y cada vez que cambie la ruta, encontrará el enlace correspondiente y añadirá la clase active al <li> correspondiente.

Puedes verlo en acción aquí: http://jsfiddle.net/8mcedv3b/

Ejemplo de HTML:

<ul class="nav navbar-nav" bs-active-link>
  <li><a href="/home">Home</a></li>
  <li><a href="/contact">Contact</a></li>
</ul>

Javascript:

angular.module('appName')
.directive('bsActiveLink', ['$location', function ($location) {
return {
    restrict: 'A', //use as attribute 
    replace: false,
    link: function (scope, elem) {
        //after the route has changed
        scope.$on("$routeChangeSuccess", function () {
            var hrefs = ['/#' + $location.path(),
                         '#' + $location.path(), //html5: false
                         $location.path()]; //html5: true
            angular.forEach(elem.find('a'), function (a) {
                a = angular.element(a);
                if (-1 !== hrefs.indexOf(a.attr('href'))) {
                    a.parent().addClass('active');
                } else {
                    a.parent().removeClass('active');   
                };
            });     
        });
    }
}
}]);

Respuesta #3

Puedes echar un vistazo a AngularStrap, la directiva de la barra de navegación parece ser lo que estás buscando:

https://github.com/mgcrea/angular-strap/blob/master/src/navbar/navbar.js

.directive('bsNavbar', function($location) {
  'use strict';

  return {
    restrict: 'A',
    link: function postLink(scope, element, attrs, controller) {
      // Watch for the $location
      scope.$watch(function() {
        return $location.path();
      }, function(newValue, oldValue) {

        $('li[data-match-route]', element).each(function(k, li) {
          var $li = angular.element(li),
            // data('match-rout') does not work with dynamic attributes
            pattern = $li.attr('data-match-route'),
            regexp = new RegExp('^' + pattern + '$', ['i']);

          if(regexp.test(newValue)) {
            $li.addClass('active');
          } else {
            $li.removeClass('active');
          }

        });
      });
    }
  };
});

Para usar esta directiva:

  1. Descarga AngularStrap desde http://mgcrea.github.io/angular-strap/

  2. Incluye el script en tu página después de bootstrap.js:
    <script src="lib/angular-strap.js"></script>

  3. Agrega las directivas a tu módulo:
    angular.module('myApp', ['$strap.directives'])

  4. Agrega la directiva a tu barra de navegación:
    <div class="navbar" bs-navbar>

  5. Agrega expresiones regulares en cada elemento de navegación:
    <li data-match-route="/about"><a href="#/about">Acerca de</a></li>

Respuesta #4

Aquí hay un enfoque simple que funciona bien con Angular.

<ul class="nav navbar-nav">
    <li ng-class="{ active: isActive('/View1') }"><a href="#/View1">View 1</a></li>
    <li ng-class="{ active: isActive('/View2') }"><a href="#/View2">View 2</a></li>
    <li ng-class="{ active: isActive('/View3') }"><a href="#/View3">View 3</a></li>
</ul>

Dentro de tu controlador AngularJS:

$scope.isActive = function (viewLocation) {
     var active = (viewLocation === $location.path());
     return active;
};

Respuesta #5

Si estás trabajando con el router de Angular, la directiva RouterLinkActive se puede usar de manera realmente elegante:

<ul class="navbar-nav">
  <li class="nav-item"><a class="nav-link" routerLink="home" routerLinkActive="active">Home</a></li>
  <li class="nav-item"><a class="nav-link" routerLink="gallery" routerLinkActive="active">Gallery</a></li>
  <li class="nav-item"><a class="nav-link" routerLink="pricing" routerLinkActive="active">Prices</a></li>
  <li class="nav-item"><a class="nav-link" routerLink="contact" routerLinkActive="active">Contact</a></li>
</ul>

Artículos relacionados