Suivant les conseils de Pavel d'utiliser une directive personnalisée, voici une version qui ne nécessite l'ajout d'aucune charge utile à routeConfig, est super déclarative et peut être adaptée pour réagir à n'importe quel niveau du chemin, en changeant simplement celui auquel slice()
vous faites attention. .
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");
}
});
}
};
});
Nous atteignons nos objectifs en écoutant l' $routeChangeSuccess
événement, plutôt qu'en plaçant un $watch
sur le chemin. Je travaille avec la conviction que cela signifie que la logique devrait fonctionner moins souvent, car je pense que les montres tirent à chaque $digest
cycle.
Appelez-le en passant votre argument au niveau du chemin sur la déclaration de directive. Ceci spécifie avec quel morceau du $ location.path () actuel vous voulez faire correspondre votre href
attribut.
<li class="nav_tab"><a href="#/home" detect-active-tab="1">HOME</a></li>
Donc, si vos onglets doivent réagir au niveau de base du chemin, faites l'argument «1». Ainsi, lorsque location.path () est "/ home", il correspondra au "# / home" dans le fichier href
. Si vous avez des onglets qui doivent réagir au deuxième niveau, au troisième ou au 11e du chemin, ajustez en conséquence. Ce découpage de 1 ou plus contournera le néfaste '#' dans le href, qui vivra à l'index 0.
La seule exigence est que vous invoquiez sur un <a>
, car l'élément suppose la présence d'un href
attribut, qu'il comparera au chemin actuel. Cependant, vous pouvez vous adapter assez facilement pour lire / écrire un élément parent ou enfant, si vous préférez invoquer sur le <li>
ou quelque chose. Je creuse cela parce que vous pouvez le réutiliser dans de nombreux contextes en faisant simplement varier l'argument pathLevel. Si la profondeur de lecture était supposée dans la logique, vous auriez besoin de plusieurs versions de la directive à utiliser avec plusieurs parties de la navigation.
EDIT 18/03/14: La solution n'était pas suffisamment généralisée et s'activerait si vous définissiez un argument pour la valeur de 'activeTab' qui retournait undefined
à la fois $location.path()
et à l'élément href
. Parce que: undefined === undefined
. Mis à jour pour corriger cette condition.
En travaillant là-dessus, j'ai réalisé qu'il aurait dû y avoir une version que vous pouvez simplement déclarer sur un élément parent, avec une structure de modèle comme celle-ci:
<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>
Notez que cette version ne ressemble plus à distance au HTML de style Bootstrap. Mais, c'est plus moderne et utilise moins d'éléments, donc j'y suis partial. Cette version de la directive, ainsi que l'original, sont désormais disponibles sur Github en tant que module intégré que vous pouvez simplement déclarer en tant que dépendance. Je serais heureux de les bower, si quelqu'un les utilise réellement.
De plus, si vous voulez une version compatible avec le bootstrap qui inclut <li>
les, vous pouvez aller avec le module Tabs angular-ui-bootstrap , qui je pense est sorti après cet article original, et qui est peut-être encore plus déclaratif que celui-ci. C'est moins concis pour les choses de base, mais vous offre des options supplémentaires, comme des onglets désactivés et des événements déclaratifs qui se déclenchent lors de l'activation et de la désactivation.