J'ai des routes définies dans AngularJS comme ceci:
$routeProvider
.when('/dashboard', {templateUrl:'partials/dashboard', controller:widgetsController})
.when('/lab', {templateUrl:'partials/lab', controller:widgetsController})
J'ai quelques liens sur la barre supérieure sous forme d'onglets. Comment puis-je ajouter une classe «active» à un onglet en fonction du modèle ou de l'url actuel?
javascript
html
angularjs
Sergueï Basharov
la source
la source
Réponses:
Un moyen de résoudre ce problème sans avoir à compter sur les URL consiste à ajouter un attribut personnalisé à chaque partiel lors de la
$routeProvider
configuration, comme ceci:Exposez
$route
dans votre contrôleur:Définissez la
active
classe en fonction de l'onglet actif actuel:la source
$scope.activeTab = $route.current.activetab
pour que vous puissiez garder le html un peu plus propre.$rootScope
astuce de @ Lucas ci-dessous pour le rendre disponible dans toutes les étendues.Une façon de faire serait d'utiliser la directive ngClass et le service $ location. Dans votre modèle, vous pouvez faire:
où
isActive
serait une fonction dans une portée définie comme ceci:Voici le jsFiddle complet: http://jsfiddle.net/pkozlowski_opensource/KzAfG/
Répéter
ng-class="{active:isActive('/dashboard')}"
sur chaque onglet de navigation peut être fastidieux (si vous avez de nombreux onglets), donc cette logique pourrait être un candidat pour une directive très simple.la source
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. .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.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'unhref
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émenthref
. 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:
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.la source
ul
, et devraient peut-être simplement être des collections d'ancres, enveloppées par unnav
élément de regroupement ou autre. Traiter avec la couche intermédiaire deli
's est une complexité supplémentaire sans gain, surtout maintenant que nous avons l'nav
élément à notre disposition pour clarifier ce qui se passe.@ rob-juurlink J'ai un peu amélioré votre solution:
au lieu de chaque itinéraire nécessitant un onglet actif; et ayant besoin de définir l'onglet actif dans chaque contrôleur, je fais ceci:
Et le HTML ressemble à ceci. L'activetab est juste l'url qui se rapporte à cet itinéraire. Cela supprime simplement le besoin d'ajouter du code dans chaque contrôleur (en faisant glisser des dépendances comme $ route et $ rootScope si c'est la seule raison pour laquelle ils sont utilisés)
la source
Peut-être qu'une directive comme celle-ci pourrait résoudre votre problème: http://jsfiddle.net/p3ZMR/4/
HTML
JS
la source
La solution la plus simple ici:
Comment définir la classe active de la barre de navigation bootstrap avec Angular JS?
Lequel est:
Utilisez ng-controller pour exécuter un seul contrôleur en dehors de ng-view:
et inclure dans controllers.js:
la source
Je recommande d'utiliser le module state.ui qui non seulement prend en charge les vues multiples et imbriquées, mais facilite également ce type de travail (code ci-dessous cité):
Ça vaut la peine d'être lu.
la source
Voici une autre version de XMLillies w / domi's LI change qui utilise une chaîne de recherche au lieu d'un niveau de chemin. Je pense que c'est un peu plus évident ce qui se passe pour mon cas d'utilisation.
Le HTML ressemble maintenant à:
la source
J'ai trouvé la réponse de XMLilley la meilleure et la plus adaptable et non intrusive.
Cependant, j'ai eu un petit problème.
Pour une utilisation avec bootstrap nav, voici comment je l'ai modifié:
J'ai ajouté "if (attrs.href! = Undefined)" car cette fonction est appelée deux fois, la deuxième fois produisant une erreur.
Quant au html:
la source
Exemple de bootstrap.
Si vous utilisez Angulars built in routing (ngview), cette directive peut être utilisée:
En supposant que votre balisage ressemble à ceci:
J'aime que ce soit de le faire puisque vous pouvez définir le nom de la classe que vous voulez dans votre attribut.
la source
Vous pouvez également simplement injecter l'emplacement dans la portée et l'utiliser pour déduire le style de la navigation:
Ensuite, utilisez-le dans votre
ng-class
:la source
une autre façon est d'utiliser ui-sref-active
Une directive travaillant avec ui-sref pour ajouter des classes à un élément lorsque l'état de la directive ui-sref associée est actif, et les supprimer quand il est inactif. Le cas d'utilisation principal est de simplifier l'apparence spéciale des menus de navigation reposant sur ui-sref, en faisant apparaître le bouton de menu de l'état "actif" différemment, en le distinguant des éléments de menu inactifs.
Usage:
ui-sref-active = 'class1 class2 class3' - les classes "class1", "class2" et "class3" sont chacune ajoutées à l'élément de directive lorsque l'état de l'interface ui-sref est actif, et supprimées lorsqu'il est inactif.
Exemple:
Compte tenu du modèle suivant,
lorsque l'état de l'application est "app.user" et contient le paramètre d'état "user" avec la valeur "bilbobaggins", le code HTML résultant apparaîtra comme
Le nom de la classe est interpolé une fois pendant le temps de liaison des directives (toute modification ultérieure de la valeur interpolée est ignorée). Plusieurs classes peuvent être spécifiées dans un format séparé par des espaces.
Utilisez la directive ui-sref-opts pour passer des options à $ state.go (). Exemple:
la source
Je suis d'accord avec le post de Rob sur le fait d'avoir un attribut personnalisé dans le contrôleur. Apparemment, je n'ai pas assez de représentants pour commenter. Voici le jsfiddle qui a été demandé:
exemple html
exemple app.js
http://jsfiddle.net/HrdR6/
la source
Et utilisez ce qui suit dans le modèle:
la source
J'avais besoin d'une solution qui ne nécessite pas de modification des contrôleurs, car pour certaines pages, nous ne rendons que des modèles et il n'y a pas de contrôleur du tout. Merci aux précédents commentateurs qui ont suggéré d'utiliser,
$routeChangeSuccess
j'ai trouvé quelque chose comme ceci:Cela ne dépend pas des URL et il est donc très facile de le configurer pour toutes les sous-pages, etc.
la source
Je ne me souviens pas où j'ai trouvé cette méthode, mais elle est assez simple et fonctionne bien.
HTML:
CSS:
la source
Si vous utilisez ngRoute (pour le routage), votre application aura la configuration ci-dessous,
Maintenant, ajoutez simplement un contrôleur dans cette configuration comme ci-dessous,
Comme vous l'avez mentionné onglet actif dans votre configuration, il ne vous reste plus qu'à ajouter une classe active dans votre balise
<li>
ou<a>
. Comme,Ce qui signifie que chaque fois que l'utilisateur clique sur la page à propos, cela identifiera automatiquement l'onglet actuel et appliquera la classe css active.
J'espère que ça aide!
la source
Je suis venu ici pour une solution ... bien que les solutions ci-dessus fonctionnent bien, mais les ont trouvées un peu complexes inutiles. Pour les personnes qui recherchent toujours une solution simple et soignée, elle fera parfaitement l'affaire.
la source