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.