Establecer estilo de pestaña activa con AngularJS

144

Tengo rutas establecidas en AngularJS como esta:

$routeProvider
    .when('/dashboard', {templateUrl:'partials/dashboard', controller:widgetsController})
    .when('/lab', {templateUrl:'partials/lab', controller:widgetsController})

Tengo algunos enlaces en la barra superior con el estilo de pestañas. ¿Cómo puedo agregar la clase 'activa' a una pestaña dependiendo de la plantilla o URL actual?

Sergei Basharov
fuente
44
@AminMeyghani ¿Cómo puede esta pregunta ser un duplicado de la pregunta que se hizo casi un año después ?
Regente

Respuestas:

274

Una forma de resolver esto sin tener que depender de las URL es agregar un atributo personalizado a cada parcial durante la $routeProviderconfiguración, de esta manera:

$routeProvider.
    when('/dashboard', {
        templateUrl: 'partials/dashboard.html',
        controller: widgetsController,
        activetab: 'dashboard'
    }).
    when('/lab', {
        templateUrl: 'partials/lab.html',
        controller: widgetsController,
        activetab: 'lab'
    });

Exponer $routeen su controlador:

function widgetsController($scope, $route) {
    $scope.$route = $route;
}

Establezca la activeclase en función de la pestaña activa actual:

<li ng-class="{active: $route.current.activetab == 'dashboard'}"></li>
<li ng-class="{active: $route.current.activetab == 'lab'}"></li>
Rob Juurlink
fuente
3
Esta es la mejor solución que he visto hasta ahora porque admite URL dinámicas como / foo /: bar.
martinpaulucci
3
En realidad no he podido hacer que esto funcione. ¿Serías capaz de proporcionar un plnkr?
PPPaul
9
Solo una cosa: mejor configurado $scope.activeTab = $route.current.activetabpara que pueda mantener el html un poco más limpio.
Christoph
2
Esto no funciona en AngularJS 1.0.8. $ route.current no está definido.
Bagre
2
Combina esto con el $rootScopetruco de @ Lucas a continuación para que esté disponible en todos los ámbitos.
colllin
134

Una forma de hacerlo sería mediante el uso de la directiva ngClass y el servicio $ location. En su plantilla puede hacer:

ng-class="{active:isActive('/dashboard')}"

donde isActivesería una función en un ámbito definido así:

myApp.controller('MyCtrl', function($scope, $location) {
    $scope.isActive = function(route) {
        return route === $location.path();
    }
});

Aquí está el jsFiddle completo: http://jsfiddle.net/pkozlowski_opensource/KzAfG/

Repetir ng-class="{active:isActive('/dashboard')}"en cada pestaña de navegación puede ser tedioso (si tiene muchas pestañas), por lo que esta lógica podría ser un candidato para una directiva muy simple.

pkozlowski.opensource
fuente
1
Me tomó mucho tiempo antes de encontrar 'directivas muy simples' para que en realidad fueran muy simples de escribir, así que proporcioné una a continuación. :-) Debe ser reutilizable en una variedad de contextos, sin configuración no declarativa.
XML
1
Mirando el jsFiddle, ¿cómo configura la página actual activa en la carga de la página? El ejemplo solo funciona cuando un usuario hace clic en una opción. Por ejemplo, es posible que desee que se resalte una navegación de "inicio" al aterrizar en la página de inicio desde un enlace externo.
thathurtabit
Ahh me estaba rascando la cabeza por un momento sobre esto. ¡Gracias!
masterwok
41

Siguiendo el consejo de Pavel de usar una directiva personalizada, aquí hay una versión que requiere no agregar carga útil a routeConfig, es súper declarativa y puede adaptarse para reaccionar a cualquier nivel de la ruta, simplemente cambiando a cuál slice()de ellos le está prestando atención. .

app.directive('detectActiveTab', function ($location) {
    return {
      link: function postLink(scope, element, attrs) {
        scope.$on("$routeChangeSuccess", function (event, current, previous) {
            /*  
                Designed for full re-usability at any path, any level, by using 
                data from attrs. Declare like this: 
                <li class="nav_tab">
                  <a href="#/home" detect-active-tab="1">HOME</a>
                </li> 
            */

            // This var grabs the tab-level off the attribute, or defaults to 1
            var pathLevel = attrs.detectActiveTab || 1,
            // This var finds what the path is at the level specified
                pathToCheck = $location.path().split('/')[pathLevel] || 
                  "current $location.path doesn't reach this level",
            // This var finds grabs the same level of the href attribute
                tabLink = attrs.href.split('/')[pathLevel] || 
                  "href doesn't include this level";
            // Above, we use the logical 'or' operator to provide a default value
            // in cases where 'undefined' would otherwise be returned.
            // This prevents cases where undefined===undefined, 
            // possibly causing multiple tabs to be 'active'.

            // now compare the two:
            if (pathToCheck === tabLink) {
              element.addClass("active");
            }
            else {
              element.removeClass("active");
            }
        });
      }
    };
  });

Estamos logrando nuestros objetivos al escuchar el $routeChangeSuccessevento, en lugar de colocar un $watchen el camino. Trabajo bajo la creencia de que esto significa que la lógica debería ejecutarse con menos frecuencia, ya que creo que los relojes se disparan en cada $digestciclo.

Invoque pasando su argumento de nivel de ruta en la declaración de directiva. Esto especifica con qué parte del $ location.path () actual con el que desea hacer coincidir su hrefatributo.

<li class="nav_tab"><a href="#/home" detect-active-tab="1">HOME</a></li>

Entonces, si sus pestañas deben reaccionar al nivel base de la ruta, haga el argumento '1'. Por lo tanto, cuando location.path () es "/ home", coincidirá con "# / home" en el href. Si tiene pestañas que deberían reaccionar al segundo nivel, al tercero o al undécimo del camino, ajústelo en consecuencia. Este corte de 1 o mayor evitará el nefasto '#' en el href, que vivirá en el índice 0.

El único requisito es que invoque en un <a>, ya que el elemento está asumiendo la presencia de un hrefatributo, que se comparará con la ruta actual. Sin embargo, puede adaptarse con bastante facilidad para leer / escribir un elemento primario o secundario, si prefiere invocar en <li>o algo. Excavo esto porque puedes reutilizarlo en muchos contextos simplemente variando el argumento pathLevel. Si la profundidad para leer se asumiera en la lógica, necesitaría múltiples versiones de la directiva para usar con múltiples partes de la navegación.


EDITAR 18/03/14: La solución se generalizó de manera inadecuada y se activaría si definiera un argumento para el valor de 'activeTab' que se devolvió undefinedcontra ambos $location.path()y el elemento href. Debido a que: undefined === undefined. Actualizado para corregir esa condición.

Mientras trabajaba en eso, me di cuenta de que debería haber una versión que puede declarar en un elemento principal, con una estructura de plantilla como esta:

<nav id="header_tabs" find-active-tab="1">
    <a href="#/home" class="nav_tab">HOME</a>
    <a href="#/finance" class="nav_tab">Finance</a>
    <a href="#/hr" class="nav_tab">Human Resources</a>
    <a href="#/quarterly" class="nav_tab">Quarterly</a>
</nav>

Tenga en cuenta que esta versión ya no se parece remotamente al HTML de estilo Bootstrap. Pero, es más moderno y usa menos elementos, así que soy parcial. Esta versión de la directiva, más el original, ahora están disponibles en Github como un módulo desplegable que puede declarar como una dependencia. Estaría encantado de darles energía, si alguien realmente los usa.

Además, si quieres una versión compatible con bootstrap que incluya la versión <li>'s', puedes usar el módulo de pestañas angular-ui-bootstrap , que creo que salió después de esta publicación original, y que quizás sea aún más declarativo que este. Es menos conciso para cosas básicas, pero le proporciona algunas opciones adicionales, como pestañas deshabilitadas y eventos declarativos que se activan al activar y desactivar.

XML
fuente
44
¡No podía creer que nadie realmente votara por esto! Aquí están mis 2 centavos. Aunque hay un pequeño error en el código, creo que se supone que 'tabLevel' es 'activeTab'. Y para el estilo Bootstrap, es posible que desee agregar la clase 'activa' al elemento LI en lugar del elemento A. Pero esto solo requiere un cambio menor.
David Lin
1
Tiene toda la razón acerca de activeTab, @DavidLin. Editado Pero no estoy enamorado de la estructura de Bootstrap, de ahí una diferencia deliberada allí. De hecho, estoy empezando a pensar que las abstracciones de navegación pueden no pertenecer en ulabsoluto, y tal vez deberían ser solo colecciones de anclas, envueltas por uno navu otro elemento de agrupación. Tratar con la capa intermedia de li's es una complejidad añadida sin resultado, particularmente ahora que tenemos el navelemento a nuestra disposición para dejar en claro lo que está sucediendo.
XML
Esto es simple y brillante. Me sorprendió que no hubiera algo así en Angular para verificar la ruta en la que estás.
Intellix
1
Para que funcione con bootstrap3, todo lo que tiene que hacer es cambiar `element.addClass (" active ");` a `element.parent ('li'). AddClass (" active ");` Creo que podría ser mejor nombrado, sin embargo, algo como is-active-tab insead de active-tab que parece declarar que la pestaña está activa. De lo contrario, esta es una directiva muy buena. Vea este cambio en la respuesta de @domi
boatcoder
La mejor solución en esta página, no puedo creer que tenga tan pocos votos positivos.
Karolis
27

@ rob-juurlink He mejorado un poco tu solución:

en lugar de que cada ruta necesite una pestaña activa; y necesitando configurar la pestaña activa en cada controlador hago esto:

var App = angular.module('App',[]);
App.config(['$routeProvider', function($routeProvider){
  $routeProvider.
  when('/dashboard', {
    templateUrl: 'partials/dashboard.html',
    controller: Ctrl1
  }).
  when('/lab', {
    templateUrl: 'partials/lab.html',
    controller: Ctrl2
  });
}]).run(['$rootScope', '$location', function($rootScope, $location){
   var path = function() { return $location.path();};
   $rootScope.$watch(path, function(newVal, oldVal){
     $rootScope.activetab = newVal;
   });
}]);

Y el HTML se ve así. La pestaña activa es solo la url que se relaciona con esa ruta. Esto simplemente elimina la necesidad de agregar código en cada controlador (arrastrando dependencias como $ route y $ rootScope si esta es la única razón por la que se usan)

<ul>
    <li ng-class="{active: activetab=='/dashboard'}">
       <a href="#/dashboard">dashboard</a>
    </li>
    <li ng-class="{active: activetab=='/lab'}">
       <a href="#/lab">lab</a>
    </li>
</ul>
Lucas
fuente
Muchas gracias por esta modificación. Muy agradable. ¿Tiene alguna sugerencia para configurar una pestaña activa cuando se carga la página por primera vez?
Hairgami_Master
2
Depende de lo que quieras. normalmente tendría '/' url como su controlador principal. de esa manera, cuando el usuario vaya a su url, cargará ese controlador y configurará esa pestaña como activa. En el ejemplo anterior no tengo una '/' url, así que si ese es su caso simplemente agregue un .otherwise () $ routeProvider. when ('/ dashboard', {templateUrl: 'partials / dashboard.html', controller: Ctrl1}). when ('/ lab', {templateUrl: 'partials / lab.html', controller: Ctrl2}). de lo contrario ({redirectTo: '/ dashboard'}); ¡la mejor de las suertes!
Lucas
Muchas gracias @Lucas. Eso ayudó. Por alguna razón tuve que agregar el símbolo # a mi ruta principal- cuando ('# /', {controller: FormsController, templateUrl: 'partials / dashboard.html'}).
Hairgami_Master
Prefiero de esta manera Tener un rootScope y hacer cualquier cosa en cualquier lugar
wrivas
16

Tal vez una directiva como esta podría resolver su problema: http://jsfiddle.net/p3ZMR/4/

HTML

<div ng-app="link">
<a href="#/one" active-link="active">One</a>
<a href="#/two" active-link="active">One</a>
<a href="#" active-link="active">home</a>


</div>

JS

angular.module('link', []).
directive('activeLink', ['$location', function(location) {
    return {
        restrict: 'A',
        link: function(scope, element, attrs, controller) {
            var clazz = attrs.activeLink;
            var path = attrs.href;
            path = path.substring(1); //hack because path does bot return including hashbang
            scope.location = location;
            scope.$watch('location.path()', function(newPath) {
                if (path === newPath) {
                    element.addClass(clazz);
                } else {
                    element.removeClass(clazz);
                }
            });
        }

    };

}]);
kfis
fuente
1
Tenga en cuenta que debe usar $ observe si href contiene una expresión: docs.angularjs.org/guide/directive#Attributes . Ver violín actualizado: jsfiddle.net/p3ZMR/10
Narretz
14

La solución más simple aquí:

¿Cómo configurar la clase activa bootstrap navbar con Angular JS?

Cual es:

Use ng-controller para ejecutar un solo controlador fuera de 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();
    };
}
Zymotik
fuente
2
de acuerdo, con mucho, el más fácil
AngeloS
12

Recomiendo usar el módulo state.ui que no solo admite vistas múltiples y anidadas, sino que también hace que este tipo de trabajo sea muy fácil (se cita el siguiente código):

<ul class="nav">
    <li ng-class="{ active: $state.includes('contacts') }"><a href="#{{$state.href('contacts')}}">Contacts</a></li>
    <li ng-class="{ active: $state.includes('about') }"><a href="#{{$state.href('about')}}">About</a></li>
</ul>

Vale la pena leer.

David Lin
fuente
4

Aquí hay otra versión de XMLillies w / domi LI change que usa una cadena de búsqueda en lugar de un nivel de ruta. Creo que esto es un poco más obvio lo que está sucediendo para mi caso de uso.

statsApp.directive('activeTab', function ($location) {
  return {
    link: function postLink(scope, element, attrs) {
      scope.$on("$routeChangeSuccess", function (event, current, previous) {
        if (attrs.href!=undefined) { // this directive is called twice for some reason
          // The activeTab attribute should contain a path search string to match on.
          // I.e. <li><a href="#/nested/section1/partial" activeTab="/section1">First Partial</a></li>
          if ($location.path().indexOf(attrs.activeTab) >= 0) {
            element.parent().addClass("active");//parent to get the <li>
          } else {
            element.parent().removeClass("active");
          }
        }
      });
    }
  };
});

HTML ahora se ve así:

<ul class="nav nav-tabs">
  <li><a href="#/news" active-tab="/news">News</a></li>
  <li><a href="#/some/nested/photos/rawr" active-tab="/photos">Photos</a></li>
  <li><a href="#/contact" active-tab="/contact">Contact</a></li>
</ul>
Dave Rapin
fuente
3

Encontré la respuesta de XMLilley la mejor y más adaptable y no intrusiva.

Sin embargo, tuve un pequeño problema técnico.

Para usar con el navegador de arranque, así es como lo modifiqué:

app.directive('activeTab', function ($location) {
    return {
      link: function postLink(scope, element, attrs) {
        scope.$on("$routeChangeSuccess", function (event, current, previous) {
            /*  designed for full re-usability at any path, any level, by using 
                data from attrs
                declare like this: <li class="nav_tab"><a href="#/home" 
                                   active-tab="1">HOME</a></li> 
            */
            if(attrs.href!=undefined){// this directive is called twice for some reason
                // this var grabs the tab-level off the attribute, or defaults to 1
                var pathLevel = attrs.activeTab || 1,
                // this var finds what the path is at the level specified
                    pathToCheck = $location.path().split('/')[pathLevel],
                // this var finds grabs the same level of the href attribute
                    tabLink = attrs.href.split('/')[pathLevel];
                // now compare the two:
                if (pathToCheck === tabLink) {
                  element.parent().addClass("active");//parent to get the <li>
                }
                else {
                  element.parent().removeClass("active");
                }
            }
        });
      }
    };
  });

Agregué "if (attrs.href! = Undefined)" porque esta función se llama dos veces, la segunda vez produce un error.

En cuanto al html:

<ul class="nav nav-tabs">
   <li class="active" active-tab="1"><a href="#/accueil" active-tab="1">Accueil</a></li>
   <li><a active-tab="1" href="#/news">News</a></li>
   <li><a active-tab="1" href="#/photos" >Photos</a></li>
   <li><a active-tab="1" href="#/contact">Contact</a></li>
</ul>
domi
fuente
nvm, fue mi culpa que esto se llamara dos veces. Supongo que "if (attrs.href! = Undefined)" no es necesario.
domi
3

Ejemplo de Bootstrap.

Si está utilizando enrutadores angulares integrados (ngview), esta directiva se puede utilizar:

angular.module('myApp').directive('classOnActiveLink', [function() {
    return {
        link: function(scope, element, attrs) {

            var anchorLink = element.children()[0].getAttribute('ng-href') || element.children()[0].getAttribute('href');
            anchorLink = anchorLink.replace(/^#/, '');

            scope.$on("$routeChangeSuccess", function (event, current) {
                if (current.$$route.originalPath == anchorLink) {
                    element.addClass(attrs.classOnActiveLink);
                }
                else {
                    element.removeClass(attrs.classOnActiveLink);
                }
            });

        }
    };
}]);

Suponiendo que su marcado se vea así:

    <ul class="nav navbar-nav">
        <li class-on-active-link="active"><a href="/orders">Orders</a></li>
        <li class-on-active-link="active"><a href="/distributors">Distributors</a></li>
    </ul>

Me gusta que esto fuera así, ya que puedes establecer el nombre de la clase que deseas en tu atributo.

Michael Falck Wedelgård
fuente
2

También puede simplemente inyectar la ubicación en el alcance y usarla para deducir el estilo para la navegación:

function IndexController( $scope, $rootScope, $location ) {
  $rootScope.location = $location;
  ...
}

Luego úsalo en tu ng-class:

<li ng-class="{active: location.path() == '/search'}">
  <a href="/search">Search><a/>
</li>
Der Hochstapler
fuente
¿No debería ser $ root.location.path () en el marcado?
Irshu
@Irshu: Eso podría ser más limpio, pero el enfoque anterior también funcionó para mí.
Der Hochstapler
2

una forma alternativa es usar ui-sref-active

Una directiva que trabaja junto con ui-sref para agregar clases a un elemento cuando el estado de la directiva ui-sref relacionada está activo, y eliminarlos cuando está inactivo. El caso de uso principal es simplificar la apariencia especial de los menús de navegación que dependen de ui-sref, haciendo que el botón de menú del estado "activo" aparezca diferente, distinguiéndolo de los elementos de menú inactivos.

Uso:

ui-sref-active = 'class1 class2 class3' - las clases "class1", "class2" y "class3" se agregan al elemento directivo cuando el estado del ui-sref relacionado está activo, y se eliminan cuando está inactivo.

Ejemplo:
dada la siguiente plantilla,

<ul>
  <li ui-sref-active="active" class="item">
    <a href ui-sref="app.user({user: 'bilbobaggins'})">@bilbobaggins</a>
  </li>
  <!-- ... -->
</ul>

cuando el estado de la aplicación es "app.user" y contiene el parámetro de estado "usuario" con el valor "bilbobaggins", el HTML resultante aparecerá como

<ul>
  <li ui-sref-active="active" class="item active">
    <a ui-sref="app.user({user: 'bilbobaggins'})" href="/users/bilbobaggins">@bilbobaggins</a>
  </li>
  <!-- ... -->
</ul>

El nombre de la clase se interpola una vez durante el tiempo de enlace de las directivas (se ignoran los cambios adicionales al valor interpolado). Se pueden especificar varias clases en un formato separado por espacios.

Use la directiva ui-sref-opts para pasar opciones a $ state.go (). Ejemplo:

<a ui-sref="home" ui-sref-opts="{reload: true}">Home</a>
George Botros
fuente
Gracias. ¡Es realmente útil cuando se trabaja en un marco iónico!
Avijit Gupta
1

Estoy de acuerdo con la publicación de Rob sobre tener un atributo personalizado en el controlador. Aparentemente no tengo suficiente representante para comentar. Aquí está el jsfiddle que se solicitó:

html de muestra

<div ng-controller="MyCtrl">
    <ul>
        <li ng-repeat="link in links" ng-class="{active: $route.current.activeNav == link.type}"> <a href="{{link.uri}}">{{link.name}}</a>

        </li>
    </ul>
</div>

app.js de muestra

angular.module('MyApp', []).config(['$routeProvider', function ($routeProvider) {
    $routeProvider.when('/a', {
        activeNav: 'a'
    })
        .when('/a/:id', {
        activeNav: 'a'
    })
        .when('/b', {
        activeNav: 'b'
    })
        .when('/c', {
        activeNav: 'c'
    });
}])
    .controller('MyCtrl', function ($scope, $route) {
    $scope.$route = $route;
    $scope.links = [{
        uri: '#/a',
        name: 'A',
        type: 'a'
    }, {
        uri: '#/b',
        name: 'B',
        type: 'b'
    }, {
        uri: '#/c',
        name: 'C',
        type: 'c'
    }, {
        uri: '#/a/detail',
        name: 'A Detail',
        type: 'a'
    }];
});

http://jsfiddle.net/HrdR6/

jasontwong
fuente
Me gusta el enfoque basado en datos para la lista de enlaces. Y, algunos pueden optar por mover la matriz de enlaces a un servicio / fábrica.
Grant Lindsay
1
'use strict';

angular.module('cloudApp')
  .controller('MenuController', function ($scope, $location, CloudAuth) {
    $scope.menu = [
      {
        'title': 'Dashboard',
        'iconClass': 'fa fa-dashboard',
        'link': '/dashboard',
        'active': true
      },
      {
        'title': 'Devices',
        'iconClass': 'fa fa-star',
        'link': '/devices'
      },
      {
        'title': 'Settings',
        'iconClass': 'fa fa-gears',
        'link': '/settings'
      }
    ];
    $location.path('/dashboard');
    $scope.isLoggedIn = CloudAuth.isLoggedIn;
    $scope.isAdmin = CloudAuth.isAdmin;
    $scope.isActive = function(route) {
      return route === $location.path();
    };
  });

Y use lo siguiente en la plantilla:

<li role="presentation" ng-class="{active:isActive(menuItem.link)}" ng-repeat="menuItem in menu"><a href="{{menuItem.link}}"><i class="{{menuItem.iconClass}}"></i>&nbsp;&nbsp;{{menuItem.title}}</a></li>
Yeshodhan Kulkarni
fuente
0

Necesitaba una solución que no requiera cambios en los controladores, porque para algunas páginas solo mostramos plantillas y no hay ningún controlador. Gracias a los comentaristas anteriores que sugirieron usar, se $routeChangeSuccessme ocurrió algo como esto:

# Directive
angular.module('myapp.directives')
.directive 'ActiveTab', ($route) ->
  restrict: 'A'

  link: (scope, element, attrs) ->
    klass = "active"

    if $route.current.activeTab? and attrs.flActiveLink is $route.current.activeTab
      element.addClass(klass)

    scope.$on '$routeChangeSuccess', (event, current) ->
      if current.activeTab? and attrs.flActiveLink is current.activeTab
        element.addClass(klass)
      else
        element.removeClass(klass)

# Routing
$routeProvider
.when "/page",
  templateUrl: "page.html"
  activeTab: "page"
.when "/other_page",
  templateUrl: "other_page.html"
  controller: "OtherPageCtrl"
  activeTab: "other_page"

# View (.jade)
a(ng-href='/page', active-tab='page') Page
a(ng-href='/other_page', active-tab='other_page') Other page

No depende de las URL y, por lo tanto, es muy fácil configurarlo para cualquier subpágina, etc.

szimek
fuente
0

No recuerdo dónde encontré este método, pero es bastante simple y funciona bien.

HTML:

<nav role="navigation">
    <ul>
        <li ui-sref-active="selected" class="inactive"><a ui-sref="tab-01">Tab 01</a></li> 
        <li ui-sref-active="selected" class="inactive"><a ui-sref="tab-02">Tab 02</a></li>
    </ul>
</nav>

CSS:

  .selected {
    background-color: $white;
    color: $light-blue;
    text-decoration: none;
    border-color: $light-grey;
  } 
cfranklin
fuente
0

Si está utilizando ngRoute (para el enrutamiento), su aplicación tendrá la siguiente configuración,

angular
  .module('appApp', [
    'ngRoute'
 ])
config(function ($routeProvider) {
    $routeProvider
      .when('/', {
        templateUrl: 'views/main.html',
        controller: 'MainCtrl',
        controllerAs: 'main'
      })
      .when('/about', {
        templateUrl: 'views/about.html',
        controller: 'AboutCtrl',
        controllerAs: 'about'
      })
}
});

Ahora, solo agregue un controlador en esta configuración como se muestra a continuación,

angular
      .module('appApp', [
        'ngRoute'
     ])
    config(function ($routeProvider) {
        $routeProvider
          .when('/', {
            templateUrl: 'views/main.html',
            controller: 'MainCtrl',
            activetab: 'main'
          })
          .when('/about', {
            templateUrl: 'views/about.html',
            controller: 'AboutCtrl',
            activetab: 'about'
          })
    }
    })
  .controller('navController', function ($scope, $route) {
    $scope.$route = $route;
  });

Como mencionó la pestaña activa en su configuración, ahora solo tiene que agregar la clase activa en su etiqueta <li>o <a>. Me gusta,

ng-class="{active: $route.current.activetab == 'about'}"

Lo que significa que cada vez que el usuario haga clic en la página Acerca de, esto identificará automáticamente la pestaña actual y aplicará la clase css activa.

¡Espero que esto ayude!

imbond
fuente
-3

Vine aquí para la solución ... aunque las soluciones anteriores están funcionando bien pero las encontraron un poco complejas innecesarias. Para las personas que todavía buscan una solución fácil y ordenada, hará la tarea perfectamente.

<section ng-init="tab=1">
                <ul class="nav nav-tabs">
                    <li ng-class="{active: tab == 1}"><a ng-click="tab=1" href="#showitem">View Inventory</a></li>
                    <li ng-class="{active: tab == 2}"><a ng-click="tab=2" href="#additem">Add new item</a></li>
                    <li ng-class="{active: tab == 3}"><a ng-click="tab=3" href="#solditem">Sold item</a></li>
                </ul>
            </section>
MGA
fuente