Définir le style d'onglet actif avec AngularJS

144

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?

Sergueï Basharov
la source
4
@AminMeyghani Comment cette question peut-elle faire double emploi avec la question posée presque un an plus tard ?
Regent

Réponses:

274

Un moyen de résoudre ce problème sans avoir à compter sur les URL consiste à ajouter un attribut personnalisé à chaque partiel lors de la $routeProviderconfiguration, comme ceci:

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

Exposez $routedans votre contrôleur:

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

Définissez la activeclasse en fonction de l'onglet actif actuel:

<li ng-class="{active: $route.current.activetab == 'dashboard'}"></li>
<li ng-class="{active: $route.current.activetab == 'lab'}"></li>
Rob Juurlink
la source
3
c'est la meilleure solution que j'ai vue jusqu'à présent car elle prend en charge les URL dynamiques comme / foo /: bar.
martinpaulucci
3
je n'ai pas été en mesure de faire fonctionner cela. seriez-vous en mesure de fournir un plnkr?
PPPaul
9
Juste une chose: mieux régler $scope.activeTab = $route.current.activetabpour que vous puissiez garder le html un peu plus propre.
Christoph
2
Cela ne fonctionne pas dans AngularJS 1.0.8. $ route.current n'est pas défini.
Catfish
2
Combinez cela avec l' $rootScopeastuce de @ Lucas ci-dessous pour le rendre disponible dans toutes les étendues.
colllin le
134

Une façon de faire serait d'utiliser la directive ngClass et le service $ location. Dans votre modèle, vous pouvez faire:

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

isActiveserait une fonction dans une portée définie comme ceci:

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

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.

pkozlowski.opensource
la source
1
Il m'a fallu beaucoup de temps avant de trouver que les «directives très simples» étaient en fait très simples à écrire, donc j'en ai fourni une ci-dessous. :-) Il devrait être réutilisable dans une variété de contextes, sans configuration non déclarative.
XML
1
En regardant le jsFiddle, comment définir la page actuelle active au chargement de la page? L'exemple ne fonctionne que lorsqu'un utilisateur clique sur une option. Par exemple, vous souhaiterez peut-être mettre en surbrillance une navigation «d'accueil» lorsque vous accédez à la page d'accueil à partir d'un lien externe.
thathurtabit
Ahh me grattait la tête un peu à ce sujet. Merci!
masterwok
41

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 $watchsur 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 $digestcycle.

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 hrefattribut.

<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 hrefattribut, 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.

XML
la source
4
Je ne pouvais pas croire que personne ne donne vraiment un vote! Voici mes 2 cents. Bien qu'il y ait une petite erreur dans le code, je pense que le «tabLevel» est censé être «activeTab». Et pour le style Bootstrap, vous voudrez peut-être ajouter la classe 'active' à l'élément LI au lieu de l'élément A. Mais cela ne nécessite que des changements mineurs.
David Lin
1
Vous avez tout à fait raison à propos de activeTab, @DavidLin. Édité. Mais je ne suis pas amoureux de la structure de Bootstrap, d'où une différence délibérée. En fait, je commence à penser que les abstractions de navigation n'appartiennent peut-être pas du tout aux abstractions de navigation ul, et devraient peut-être simplement être des collections d'ancres, enveloppées par un navélément de regroupement ou autre. Traiter avec la couche intermédiaire de li'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.
XML
C'est simple et brillant. J'ai été surpris qu'il n'y ait pas quelque chose comme ça déjà dans Angular pour vérifier l'itinéraire sur lequel vous êtes.
Intellix
1
Pour le faire fonctionner avec bootstrap3, tout ce que vous avez à faire est de changer `element.addClass (" active ");` en `element.parent ('li'). AddClass (" active ");` Je pense que ça pourrait être mieux nommé cependant, quelque chose comme is-active-tab à la place de active-tab qui semble déclarer que l'onglet est actif. Sinon, c'est une directive vraiment sympa. Voir ce changement dans la réponse de @domi
boatcoder
La meilleure solution sur cette page, je ne peux pas croire qu'il y ait si peu de votes positifs.
Karolis
27

@ 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:

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;
   });
}]);

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)

<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
la source
Merci beaucoup pour cette modification. Très agréable. Avez-vous des suggestions pour définir un onglet actif lors du premier chargement de la page?
Hairgami_Master
2
Cela dépend de ce que vous voulez. généralement vous auriez l'url '/' comme contrôleur principal. de cette façon, lorsque l'utilisateur accède à votre URL, il charge ce contrôleur et définit cet onglet comme actif. Dans l'exemple ci-dessus, je n'ai pas d'url '/', donc si c'est votre cas, ajoutez simplement un .otherwise () $ routeProvider. when ('/ dashboard', {templateUrl: 'partials / dashboard.html', controller: Ctrl1}). when ('/ lab', {templateUrl: 'partials / lab.html', controller: Ctrl2}). Autrement ({redirectTo: '/ dashboard'}); bonne chance!
Lucas le
Merci beaucoup @Lucas. Cela a aidé. Une raison pour laquelle j'ai dû ajouter le symbole # à ma route principale - when ('# /', {controller: FormsController, templateUrl: 'partials / dashboard.html'}).
Hairgami_Master
Je préfère cette façon. Avoir un rootScope et faire n'importe quoi où que ce soit
Wrivas
16

Peut-être qu'une directive comme celle-ci pourrait résoudre votre problème: 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
la source
1
Notez que vous devez utiliser $ observe si le href contient une expression: docs.angularjs.org/guide/directive#Attributes . Voir le violon mis à jour: jsfiddle.net/p3ZMR/10
Narretz
14

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:

<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>

et inclure dans controllers.js:

function HeaderController($scope, $location) 
{ 
    $scope.isActive = function (viewLocation) { 
        return viewLocation === $location.path();
    };
}
Zymotik
la source
2
d'accord, de loin le plus facile
AngeloS
12

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é):

<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>

Ça vaut la peine d'être lu.

David Lin
la source
4

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.

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");
          }
        }
      });
    }
  };
});

Le HTML ressemble maintenant à:

<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
la source
3

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é:

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");
                }
            }
        });
      }
    };
  });

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:

<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
la source
nvm, c'était de ma faute cela a été appelé deux fois. Je suppose que "if (attrs.href! = Undefined)" n'est pas nécessaire.
domi
3

Exemple de bootstrap.

Si vous utilisez Angulars built in routing (ngview), cette directive peut être utilisée:

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);
                }
            });

        }
    };
}]);

En supposant que votre balisage ressemble à ceci:

    <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>

J'aime que ce soit de le faire puisque vous pouvez définir le nom de la classe que vous voulez dans votre attribut.

Michael Falck Wedelgård
la source
2

Vous pouvez également simplement injecter l'emplacement dans la portée et l'utiliser pour déduire le style de la navigation:

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

Ensuite, utilisez-le dans votre ng-class:

<li ng-class="{active: location.path() == '/search'}">
  <a href="/search">Search><a/>
</li>
Der Hochstapler
la source
ne devrait-il pas être $ root.location.path () dans le balisage?
Irshu
@Irshu: Cela pourrait peut-être être plus propre, mais l'approche ci-dessus a également fonctionné pour moi.
Der Hochstapler
2

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,

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

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

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

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:

<a ui-sref="home" ui-sref-opts="{reload: true}">Home</a>
George Botros
la source
Merci. C'est vraiment utile quand on travaille dans un framework ionique!
Avijit Gupta
1

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

<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>

exemple app.js

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
la source
J'aime l'approche de la liste de liens basée sur les données. Et certains peuvent choisir de déplacer le tableau de liens vers un service / une usine.
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();
    };
  });

Et utilisez ce qui suit dans le modèle:

<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
la source
0

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, $routeChangeSuccessj'ai trouvé quelque chose comme ceci:

# 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

Cela ne dépend pas des URL et il est donc très facile de le configurer pour toutes les sous-pages, etc.

szimek
la source
0

Je ne me souviens pas où j'ai trouvé cette méthode, mais elle est assez simple et fonctionne 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
la source
0

Si vous utilisez ngRoute (pour le routage), votre application aura la configuration ci-dessous,

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'
      })
}
});

Maintenant, ajoutez simplement un contrôleur dans cette configuration comme ci-dessous,

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;
  });

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,

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

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!

imbiber
la source
-3

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.

<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
la source