Comment mettre en évidence un élément de menu actuel?

est-ce que AngularJS aide d'une manière ou d'une autre à mettre une classe active sur le lien de la page courante?

j'imagine qu'il y a un moyen magique de faire ça, mais je n'arrive pas à trouver.

mon menu ressemble à:

 <ul>
   <li><a class="active" href="/tasks">Tasks</a>
   <li><a href="/actions">Tasks</a>
 </ul>

et j'ai des contrôleurs pour chacune d'elles sur mes routes: TasksController et ActionsController .

mais je n'arrive pas à trouver un moyen de lier la classe "active" au a des liens vers les contrôleurs.

des indices?

202
demandé sur Blackhole 2012-09-26 03:18:57

30 réponses

à vue

<a ng-class="getClass('/tasks')" href="/tasks">Tasks</a>

contrôleur

$scope.getClass = function (path) {
  return ($location.path().substr(0, path.length) === path) ? 'active' : '';
}

avec ceci le lien tâches aura la classe active dans n'importe quelle url qui commence avec '/tasks'(par exemple '/tasks/1/reports')

260
répondu Renan Tomal Fernandes 2016-03-09 13:33:54

je suggère d'utiliser une directive sur un lien.

Mais ce n'est pas encore parfait. Attention aux hashbangs;)

voici le javascript pour la directive:

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 not return including hashbang
        scope.location = location;
        scope.$watch('location.path()', function (newPath) {
          if (path === newPath) {
            element.addClass(clazz);
          } else {
            element.removeClass(clazz);
          }
        });
      }
    };
  }]);

et voici comment il serait utilisé en 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>

après styling avec css:

.active { color: red; }
85
répondu kfis 2015-08-14 11:26:44

Voici une approche simple qui fonctionne bien avec Angular.

<ul>
    <li ng-class="{ active: isActive('/View1') }"><a href="#/View1">View 1</a></li>
    <li ng-class="{ active: isActive('/View2') }"><a href="#/View2">View 2</a></li>
    <li ng-class="{ active: isActive('/View3') }"><a href="#/View3">View 3</a></li>
</ul>

dans votre contrôleur AngularJS:

$scope.isActive = function (viewLocation) {
     var active = (viewLocation === $location.path());
     return active;
};

Ce fil a un certain nombre d'autres réponses semblables.

comment configurer bootstrap navbar active class avec Angular JS?

45
répondu Ender2050 2017-05-23 11:47:15

juste pour ajouter mes deux cents dans le débat, j'ai fait un module angulaire PUR (Pas de jQuery), et il fonctionnera également avec des URL de hachage contenant des données. (par exemple #/this/is/path?this=is&some=data )

il suffit d'ajouter le module comme dépendance et auto-active à l'un des ancêtres du menu. Comme ceci:

<ul auto-active>
    <li><a href="#/">main</a></li>
    <li><a href="#/first">first</a></li>
    <li><a href="#/second">second</a></li>
    <li><a href="#/third">third</a></li>
</ul>

et le module ressemblent à ceci:

(function () {
    angular.module('autoActive', [])
        .directive('autoActive', ['$location', function ($location) {
        return {
            restrict: 'A',
            scope: false,
            link: function (scope, element) {
                function setActive() {
                    var path = $location.path();
                    if (path) {
                        angular.forEach(element.find('li'), function (li) {
                            var anchor = li.querySelector('a');
                            if (anchor.href.match('#' + path + '(?=\?|$)')) {
                                angular.element(li).addClass('active');
                            } else {
                                angular.element(li).removeClass('active');
                            }
                        });
                    }
                }

                setActive();

                scope.$on('$locationChangeSuccess', setActive);
            }
        }
    }]);
}());

(vous pouvez bien sûr utiliser la partie directive)

Il est également intéressant de noter que cela ne fonctionne pas pour les hachures vides (par exemple example.com/# ou tout simplement example.com ) il doit avoir au moins example.com/#/ ou tout simplement example.com#/ . Mais cela se produit automatiquement avec ngResource et autres.

Et voici le violon: http://jsfiddle.net/gy2an/8 /

31
répondu Pylinux 2016-01-11 07:38:35

dans mon cas j'ai résolu ce problème en créant un simple contrôleur responsable de la navigation

angular.module('DemoApp')
  .controller('NavigationCtrl', ['$scope', '$location', function ($scope, $location) {
    $scope.isCurrentPath = function (path) {
      return $location.path() == path;
    };
  }]);

et en ajoutant simplement la classe ng à l'élément comme ceci:

<ul class="nav" ng-controller="NavigationCtrl">
  <li ng-class="{ active: isCurrentPath('/') }"><a href="#/">Home</a></li>
  <li ng-class="{ active: isCurrentPath('/about') }"><a href="#/about">About</a></li>
  <li ng-class="{ active: isCurrentPath('/contact') }"><a href="#/contact">Contact</a></li>
</ul>
22
répondu Djamel 2013-09-19 12:30:39

il existe une directive ng-class qui lie les variables et la classe css. Il accepte également l'objet (className vs bool valeur des paires).

Voici l'exemple, http://plnkr.co/edit/SWZAqj

13
répondu Tosh 2012-09-25 23:53:13

la réponse de @Renan-tomal-fernandes est bonne, mais a besoin de quelques améliorations pour fonctionner correctement. Comme il était, il détectait toujours le lien vers la page d'accueil ( / ) comme déclenché, même si vous étiez dans une autre section.

donc je l'ai amélioré un peu, voici le code. Je travaille avec Bootstrap donc la partie active est dans l'élément <li> au lieu du <a> .

contrôleur

$scope.getClass = function(path) {
    var cur_path = $location.path().substr(0, path.length);
    if (cur_path == path) {
        if($location.path().substr(0).length > 1 && path.length == 1 )
            return "";
        else
            return "active";
    } else {
        return "";
    }
}

Modèle

<div class="nav-collapse collapse">
  <ul class="nav">
    <li ng-class="getClass('/')"><a href="#/">Home</a></li>
    <li ng-class="getClass('/contents/')"><a href="#/contests/">Contents</a></li>
    <li ng-class="getClass('/data/')"><a href="#/data/">Your data</a></li>
  </ul>
</div>
13
répondu holographix 2017-05-23 12:26:23

pour AngularUI utilisateurs du routeur:

<a ui-sref-active="active" ui-sref="app">

et qui placera une classe active sur l'objet sélectionné.

13
répondu frankie4fingers 2015-06-11 11:29:09

Voici la solution que j'ai trouvé après avoir lu quelques-unes des excellentes suggestions ci-dessus. Dans ma situation particulière, j'ai essayé d'utiliser bootstraps tabs component comme mon menu, mais je ne voulais pas utiliser la version Angular-UI de ceci parce que je veux que les onglets agissent comme un menu, où chaque onglet est signet-able, plutôt que les onglets agissant comme navigation pour une page unique. (Voir http://angular-ui.github.io/bootstrap/#/tabs si vous êtes intéressée à ce que l'Angulaire de l'INTERFACE utilisateur de la version de bootstrap onglets ressemble).

j'ai vraiment aimé la réponse de kfis à propos de la création de votre propre directive pour gérer cela, mais il a semblé encombrant d'avoir une directive qui devait être placée sur chaque lien. J'ai donc créé ma propre directive angulaire qui est placée à la place une fois sur le ul . Juste au cas où quelqu'un d'autre essaie de faire la même chose, j'ai pensé que je le posterais ici, bien que, comme je l'ai dit, beaucoup des solutions ci-dessus travaillent ainsi. Il s'agit d'une solution un peu plus complexe en ce qui concerne le javascript, mais elle crée un composant réutilisable avec un balisage minimal.

voici le javascript pour la directive et le fournisseur de route pour ng:view :

var app = angular.module('plunker', ['ui.bootstrap']).
  config(['$routeProvider', function($routeProvider) {
    $routeProvider.
        when('/One', {templateUrl: 'one.html'}).
        when('/Two', {templateUrl: 'two.html'}).
        when('/Three', {templateUrl: 'three.html'}).
        otherwise({redirectTo: '/One'});
  }]).
  directive('navTabs', ['$location', function(location) {
    return {
        restrict: 'A',
        link: function(scope, element) {
            var $ul = $(element);
            $ul.addClass("nav nav-tabs");

            var $tabs = $ul.children();
            var tabMap = {};
            $tabs.each(function() {
              var $li = $(this);
              //Substring 1 to remove the # at the beginning (because location.path() below does not return the #)
              tabMap[$li.find('a').attr('href').substring(1)] = $li;
            });

            scope.location = location;
            scope.$watch('location.path()', function(newPath) {
                $tabs.removeClass("active");
                tabMap[newPath].addClass("active");
            });
        }

    };

 }]);

puis dans votre html vous simplement:

<ul nav-tabs>
  <li><a href="#/One">One</a></li>
  <li><a href="#/Two">Two</a></li>
  <li><a href="#/Three">Three</a></li>
</ul>
<ng:view><!-- Content will appear here --></ng:view>

voici le piston pour cela: http://plnkr.co/edit/xwGtGqrT7kWoCKnGDHYN?p=preview .

10
répondu corinnaerin 2013-04-18 20:54:28

vous pouvez mettre en œuvre cela très simplement, voici un exemple:

<div ng-controller="MenuCtrl">
  <ul class="menu">
    <li ng-class="menuClass('home')"><a href="#home">Page1</a></li>
    <li ng-class="menuClass('about')"><a href="#about">Page2</a></li>
  </ul>

</div>

et votre contrôleur devrait être:

app.controller("MenuCtrl", function($scope, $location) {
  $scope.menuClass = function(page) {
    var current = $location.path().substring(1);
    return page === current ? "active" : "";
  };
});
8
répondu Ejaz 2016-03-06 16:25:06

utilisation angulaire de l'interface utilisateur du routeur de l'interface utilisateur-sref-active la directive https://github.com/angular-ui/ui-router/wiki/Quick-Reference#statename

<ul>
  <li ui-sref-active="active" class="item">
    <a href ui-sref="app.user({user: 'bilbobaggins'})">@bilbobaggins</a>
  </li>
  <!-- ... -->
</ul>
5
répondu Cyanny 2016-02-03 07:40:34

j'ai eu le même problème avec le menu situé à l'extérieur du champ d'application du contrôleur. Ne sais pas si c'est la meilleure solution ou un recommandé mais c'est ce qui a fonctionné pour moi. J'ai ajouté ce qui suit à ma configuration d'application:

var app = angular.module('myApp');

app.run(function($rootScope, $location){
  $rootScope.menuActive = function(url, exactMatch){
    if (exactMatch){
      return $location.path() == url;
    }
    else {
      return $location.path().indexOf(url) == 0;
    }
  }
});

alors dans la vue j'ai:

<li><a href="/" ng-class="{true: 'active'}[menuActive('/', true)]">Home</a></li>
<li><a href="/register" ng-class="{true: 'active'}[menuActive('/register')]">
<li>...</li>
4
répondu mrt 2013-03-18 15:41:25

en utilisant une directive (puisque nous faisons ici des manipulations DOM) ce qui suit est probablement le plus proche de faire les choses de la "manière angulaire":

$scope.timeFilters = [
  {'value':3600,'label':'1 hour'},
  {'value':10800,'label':'3 hours'},
  {'value':21600,'label':'6 hours'},
  {'value':43200,'label':'12 hours'},
  {'value':86400,'label':'24 hours'},
  {'value':604800,'label':'1 week'}
]

angular.module('whatever', []).directive('filter',function(){
return{
    restrict: 'A',
    template: '<li ng-repeat="time in timeFilters" class="filterItem"><a ng-click="changeTimeFilter(time)">{{time.label}}</a></li>',
    link: function linkFn(scope, lElement, attrs){

        var menuContext = attrs.filter;

        scope.changeTimeFilter = function(newTime){
          scope.selectedtimefilter = newTime;

        }

        lElement.bind('click', function(cevent){
            var currentSelection = angular.element(cevent.srcElement).parent();
            var previousSelection = scope[menuContext];

            if(previousSelection !== currentSelection){
                if(previousSelection){
                    angular.element(previousSelection).removeClass('active')
                }
                scope[menuContext] = currentSelection;

                scope.$apply(function(){
                    currentSelection.addClass('active');
                })
            }
        })
    }
}
})

alors votre HTML ressemblerait à:

<ul class="dropdown-menu" filter="times"></ul>
3
répondu Wesley Hales 2013-04-24 15:13:50

Je l'ai fait comme ceci:

var myApp = angular.module('myApp', ['ngRoute']);

myApp.directive('trackActive', function($location) {
    function link(scope, element, attrs){
        scope.$watch(function() {
            return $location.path();
        }, function(){
            var links = element.find('a');
            links.removeClass('active');
            angular.forEach(links, function(value){
                var a = angular.element(value);
                if (a.attr('href') == '#' + $location.path() ){
                    a.addClass('active');
                }
            });
        });
    }
    return {link: link};
});

cela vous permet d'avoir des liens dans une section qui a la directive track-active:

<nav track-active>
     <a href="#/">Page 1</a>
     <a href="#/page2">Page 2</a>
     <a href="#/page3">Page 3</a>
</nav>

cette approche me semble beaucoup plus propre que d'autres.

aussi, si vous utilisez jQuery, vous pouvez le rendre beaucoup plus net parce que jQlite a seulement le support de selecteur de base. Une version beaucoup plus propre avec jquery inclus avant angular include ressemblerait à ceci:

myApp.directive('trackActive', function($location) {
    function link(scope, element, attrs){
        scope.$watch(function() {
            return $location.path();
        }, function(){
            element.find('a').removeClass('active').find('[href="#'+$location.path()+'"]').addClass('active');
        });
    }
    return {link: link};
});

voici un jsFiddle

2
répondu konsumer 2014-01-24 00:09:51

ma solution à ce problème, utilisez route.current dans le gabarit angulaire.

comme vous avez la route /tasks à mettre en évidence dans votre menu, vous pouvez ajouter votre propre propriété menuItem aux routes déclarées par votre module:

$routeProvider.
  when('/tasks', {
    menuItem: 'TASKS',
    templateUrl: 'my-templates/tasks.html',
    controller: 'TasksController'
  );

puis dans votre modèle tasks.html vous pouvez utiliser la directive suivante ng-class :

<a href="app.html#/tasks" 
    ng-class="{active : route.current.menuItem === 'TASKS'}">Tasks</a>

À mon avis, c'est beaucoup plus propre que toutes les solutions proposées.

2
répondu François Maturel 2015-04-07 07:49:16

Voici une extension sur la directive kfis que j'ai fait pour permettre différents niveaux de correspondance des chemins. Essentiellement, j'ai trouvé le besoin d'assortir les chemins D'URL jusqu'à une certaine profondeur, comme l'appariement exact ne permet pas de nicher et les redirections d'état par défaut. Espérons que cette aide.

    .directive('selectedLink', ['$location', function(location) {
    return {
        restrict: 'A',
        scope:{
            selectedLink : '='
            },
        link: function(scope, element, attrs, controller) {
            var level = scope.selectedLink;
            var path = attrs.href;
            path = path.substring(1); //hack because path does not return including hashbang
            scope.location = location;
            scope.$watch('location.path()', function(newPath) {
                var i=0;
                p = path.split('/');
                n = newPath.split('/');
                for( i ; i < p.length; i++) { 
                    if( p[i] == 'undefined' || n[i] == 'undefined' || (p[i] != n[i]) ) break;
                    }

                if ( (i-1) >= level) {
                    element.addClass("selected");
                    } 
                else {
                    element.removeClass("selected");
                    }
                });
            }

        };
    }]);

Et voici comment j'utilise le lien

<nav>
    <a href="#/info/project/list"  selected-link="2">Project</a>
    <a href="#/info/company/list" selected-link="2">Company</a>
    <a href="#/info/person/list"  selected-link="2">Person</a>
</nav>

cette directive correspondra au niveau de profondeur spécifié dans l'attribut valeur de la directive. Juste signifie qu'il peut être utilisé ailleurs à plusieurs reprises.

1
répondu pkbyron 2013-07-22 13:39:22

Voici encore une autre directive pour mettre en évidence les liens actifs.

Caractéristiques principales:

  • fonctionne bien avec href qui contient des expressions angulaires dynamiques
  • Compatible avec la navigation hash-bang
  • Compatible avec Bootstrap où la classe active doit être appliquée au parent li et non au lien lui-même
  • permet de rendre le lien actif si un chemin imbriqué est actif
  • permet de désactiver le lien make s'il n'est pas actif

Code:

.directive('activeLink', ['$location', 
function($location) {
    return {
        restrict: 'A',
        link: function(scope, elem, attrs) {
            var path = attrs.activeLink ? 'activeLink' : 'href';
            var target = angular.isDefined(attrs.activeLinkParent) ? elem.parent() : elem;
            var disabled = angular.isDefined(attrs.activeLinkDisabled) ? true : false;
            var nested = angular.isDefined(attrs.activeLinkNested) ? true : false;

            function inPath(needle, haystack) {
                var current = (haystack == needle);
                if (nested) {
                    current |= (haystack.indexOf(needle + '/') == 0);
                }

                return current;
            }

            function toggleClass(linkPath, locationPath) {
                // remove hash prefix and trailing slashes
                linkPath = linkPath ? linkPath.replace(/^#!/, '').replace(/\/+$/, '') : '';
                locationPath = locationPath.replace(/\/+$/, '');

                if (linkPath && inPath(linkPath, locationPath)) {
                    target.addClass('active');
                    if (disabled) {
                        target.removeClass('disabled');
                    }
                } else {
                    target.removeClass('active');
                    if (disabled) {
                        target.addClass('disabled');
                    }
                }
            }

            // watch if attribute value changes / evaluated
            attrs.$observe(path, function(linkPath) {
                toggleClass(linkPath, $location.path());
            });

            // watch if location changes
            scope.$watch(
                function() {
                    return $location.path(); 
                }, 
                function(newPath) {
                    toggleClass(attrs[path], newPath);
                }
            );
        }
    };
}
]);

Utilisation:

exemple Simple avec expression angulaire, permet de dire $ scope.var = 2 , alors le lien sera actif si l'emplacement est / url / 2 :

<a href="#!/url/{{var}}" active-link>

exemple de Bootstrap, le parent li obtiendra la classe active:

<li>
    <a href="#!/url" active-link active-link-parent>
</li>

exemple avec des URL imbriquées, le lien sera actif si n'importe quelle url imbriquée est active (i.e. / url/1 , /url / 2 , url/1/2/... )

<a href="#!/url" active-link active-link-nested>

exemple complexe, points de lien vers une url ( /url1 ) mais sera actif si une autre est sélectionnée ( / url2 ):

<a href="#!/url1" active-link="#!/url2" active-link-nested>

exemple avec le lien handicapé, s'il n'est pas actif désactivé classe:

<a href="#!/url" active-link active-link-disabled>

Tous active-link* attributs peuvent être utilisés dans n'importe quelle combinaison, de sorte que des conditions très complexes pourraient être mises en œuvre.

1
répondu Eugene Fidelin 2014-05-29 12:37:13

si vous voulez les liens pour la directive dans un wrapper plutôt que de sélectionner chaque lien individuel (ce qui rend plus facile de regarder la portée dans Batarang), cela fonctionne assez bien aussi:

  angular.module("app").directive("navigation", [
    "$location", function($location) {
      return {
        restrict: 'A',
        scope: {},
        link: function(scope, element) {
          var classSelected, navLinks;

          scope.location = $location;

          classSelected = 'selected';

          navLinks = element.find('a');

          scope.$watch('location.path()', function(newPath) {
            var el;
            el = navLinks.filter('[href="' + newPath + '"]');

            navLinks.not(el).closest('li').removeClass(classSelected);
            return el.closest('li').addClass(classSelected);
          });
        }
      };
    }
  ]);

Markup serait juste:

    <nav role="navigation" data-navigation>
        <ul>
            <li><a href="/messages">Messages</a></li>
            <li><a href="/help">Help</a></li>
            <li><a href="/details">Details</a></li>
        </ul>
    </nav>

je dois aussi mentionner que j'utilise 'full-fat' jQuery dans cet exemple, mais vous pouvez facilement modifier ce que j'ai fait avec le filtrage et ainsi de suite.

1
répondu marksyzm 2014-07-11 11:25:29

selon la réponse de @kfis, ce sont des commentaires, et je recommande, la directive finale comme suit:

.directive('activeLink', ['$location', function (location) {
    return {
      restrict: 'A',
      link: function(scope, element, attrs, controller) {
        var clazz = attrs.activeLink;        
        var path = attrs.href||attrs.ngHref;
        path = path.substring(1); //hack because path does not return including hashbang
        scope.location = location;
        scope.$watch('window.location.href', function () {
          var newPath = (window.location.pathname + window.location.search).substr(1);
          if (path === newPath) {
            element.addClass(clazz);
          } else {
            element.removeClass(clazz);
          }
        });
      }
    };
  }]);

et voici comment il serait utilisé en 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>

après styling avec css:

.active { color: red; }
1
répondu John_J 2015-10-06 09:31:35

pour ceux qui utilisent ui-router, ma réponse est quelque peu similaire à celle de Ender2050, mais je préfère le faire via un test de nom d'état:

$scope.isActive = function (stateName) {
  var active = (stateName === $state.current.name);
  return active;
};

HTML correspondant:

<ul class="nav nav-sidebar">
    <li ng-class="{ active: isActive('app.home') }"><a ui-sref="app.home">Dashboard</a></li>
    <li ng-class="{ active: isActive('app.tiles') }"><a ui-sref="app.tiles">Tiles</a></li>
</ul>
1
répondu GONeale 2016-01-05 06:46:00

aucune des suggestions ci-dessus directive les suggestions m'ont été utiles. Si vous avez un bootstrap navbar comme ceci

<ul class="nav navbar-nav">
    <li><a ng-href="#/">Home</a></li>
    <li><a ng-href="#/about">About</a></li>
  ...
</ul>

(qui pourrait être un démarrage de $ yo angular ) alors vous voulez ajouter .active à la parent <li> liste de classe d'éléments, pas l'élément lui-même; I. e <li class="active">..</li> . Alors j'ai écrit ceci:

.directive('setParentActive', ['$location', function($location) {
  return {
    restrict: 'A',
    link: function(scope, element, attrs, controller) {
      var classActive = attrs.setParentActive || 'active',
          path = attrs.ngHref.replace('#', '');
      scope.location = $location;
      scope.$watch('location.path()', function(newPath) {
        if (path == newPath) {
          element.parent().addClass(classActive);
        } else {
          element.parent().removeClass(classActive);
        }
      })
    }
  }
}])

utilisation set-parent-active ; .active est par défaut afin de ne pas à régler

<li><a ng-href="#/about" set-parent-active>About</a></li>

et l'élément parent <li> sera .active lorsque le lien est actif. Pour utiliser une alternative .active classe comme .highlight , simplement

<li><a ng-href="#/about" set-parent-active="highlight">About</a></li>
1
répondu davidkonrad 2016-02-06 21:37:03

utilisant la Version angulaire 6 avec Bootstrap 4.1

j'ai pu le faire comme ci-dessous.

dans l'exemple ci-dessous, lorsque L'URL voit '/contact', le bootstrap actif est alors ajouté à la balise html. Lorsque L'URL change, elle est alors supprimée.

<ul>
<li class="nav-item" routerLink="/contact" routerLinkActive="active">
    <a class="nav-link" href="/contact">Contact</a>
</li>
</ul>

cette directive vous permet d'ajouter une classe CSS à un élément lorsque le lien route devient active.

plus d'informations sur site Web

1
répondu Jeacovy Gayle 2018-09-14 12:56:16

le plus important pour moi était de ne pas changer du tout le code par défaut de bootstrap. Ici, c'est mon contrôleur de menu qui cherche les options de menu et ensuite ajoute le comportement que nous voulons.

file: header.js
function HeaderCtrl ($scope, $http, $location) {
  $scope.menuLinkList = [];
  defineFunctions($scope);
  addOnClickEventsToMenuOptions($scope, $location);
}

function defineFunctions ($scope) {
  $scope.menuOptionOnClickFunction = function () {
    for ( var index in $scope.menuLinkList) {
      var link = $scope.menuLinkList[index];
      if (this.hash === link.hash) {
        link.parentElement.className = 'active';
      } else {
        link.parentElement.className = '';
      }
    }
  };
}

function addOnClickEventsToMenuOptions ($scope, $location) {
  var liList = angular.element.find('li');
  for ( var index in liList) {
    var liElement = liList[index];
    var link = liElement.firstChild;
    link.onclick = $scope.menuOptionOnClickFunction;
    $scope.menuLinkList.push(link);
    var path = link.hash.replace("#", "");
    if ($location.path() === path) {
      link.parentElement.className = 'active';
    }
  }
}

     <script src="resources/js/app/header.js"></script>
 <div class="navbar navbar-fixed-top" ng:controller="HeaderCtrl">
    <div class="navbar-inner">
      <div class="container-fluid">
        <button type="button" class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
          <span class="icon-bar"></span> <span class="icon-bar"></span> 
<span     class="icon-bar"></span>
        </button>
        <a class="brand" href="#"> <img src="resources/img/fom-logo.png"
          style="width: 80px; height: auto;">
        </a>
        <div class="nav-collapse collapse">
          <ul class="nav">
            <li><a href="#/platforms">PLATFORMS</a></li>
            <li><a href="#/functionaltests">FUNCTIONAL TESTS</a></li>
          </ul> 
        </div>
      </div>
    </div>
  </div>
0
répondu user2599258 2013-07-19 11:26:43

avait le même problème. Voici ma solution :

.directive('whenActive',
  [
    '$location',
    ($location)->
      scope: true,
      link: (scope, element, attr)->
        scope.$on '$routeChangeSuccess', 
          () ->
            loc = "#"+$location.path()
            href = element.attr('href')
            state = href.indexOf(loc)
            substate = -1

            if href.length > 3
              substate = loc.indexOf(href)
            if loc.length is 2
              state = -1

            #console.log "Is Loc: "+loc+" in Href: "+href+" = "+state+" and Substate = "+substate

            if state isnt -1 or substate isnt -1
              element.addClass 'selected'
              element.parent().addClass 'current-menu-item'
            else if href is '#' and loc is '#/'
              element.addClass 'selected'
              element.parent().addClass 'current-menu-item'
            else
              element.removeClass 'selected'
              element.parent().removeClass 'current-menu-item'
  ])
0
répondu Naxmeify 2013-11-22 20:22:08

voilà mes deux cents, ça marche très bien.

NOTE: cela ne correspond pas à la taille des enfants (ce dont j'avais besoin).

:

<a ng-class="{active: isCurrentLocation('/my-path')}"  href="/my-path" >
  Some link
</a>

contrôleur:

// make sure you inject $location as a dependency

$scope.isCurrentLocation = function(path){
    return path === $location.path()
}
0
répondu Justus Romijn 2015-03-23 19:47:32

je viens d'écrire une directive pour ça.

Utilisation:

<ul class="nav navbar-nav">
  <li active><a href="#/link1">Link 1</a></li>
  <li active><a href="#/link2">Link 2</a></li>
</ul>

mise en Œuvre:

angular.module('appName')
  .directive('active', function ($location, $timeout) {
    return {
      restrict: 'A',
      link: function (scope, element, attrs) {
        // Whenever the user navigates to a different page...
        scope.$on('$routeChangeSuccess', function () {
          // Defer for other directives to load first; this is important
          // so that in case other directives are used that this directive
          // depends on, such as ng-href, the href is evaluated before
          // it's checked here.
          $timeout(function () {
            // Find link inside li element
            var $link = element.children('a').first();

            // Get current location
            var currentPath = $location.path();

            // Get location the link is pointing to
            var linkPath = $link.attr('href').split('#').pop();

            // If they are the same, it means the user is currently
            // on the same page the link would point to, so it should
            // be marked as such
            if (currentPath === linkPath) {
              $(element).addClass('active');
            } else {
              // If they're not the same, a li element that is currently
              // marked as active needs to be "un-marked"
              element.removeClass('active');
            }
          });
        });
      }
    };
  });

Essais:

'use strict';

describe('Directive: active', function () {

  // load the directive's module
  beforeEach(module('appName'));

  var element,
      scope,
      location,
      compile,
      rootScope,
      timeout;

  beforeEach(inject(function ($rootScope, $location, $compile, $timeout) {
    scope = $rootScope.$new();
    location = $location;
    compile = $compile;
    rootScope = $rootScope;
    timeout = $timeout;
  }));

  describe('with an active link', function () {
    beforeEach(function () {
      // Trigger location change
      location.path('/foo');
    });

    describe('href', function () {
      beforeEach(function () {
        // Create and compile element with directive; note that the link
        // is the same as the current location after the location change.
        element = angular.element('<li active><a href="#/foo">Foo</a></li>');
        element = compile(element)(scope);

        // Broadcast location change; the directive waits for this signal
        rootScope.$broadcast('$routeChangeSuccess');

        // Flush timeout so we don't have to write asynchronous tests.
        // The directive defers any action using a timeout so that other
        // directives it might depend on, such as ng-href, are evaluated
        // beforehand.
        timeout.flush();
      });

      it('adds the class "active" to the li', function () {
        expect(element.hasClass('active')).toBeTruthy();
      });
    });

    describe('ng-href', function () {
      beforeEach(function () {
        // Create and compile element with directive; note that the link
        // is the same as the current location after the location change;
        // however this time with an ng-href instead of an href.
        element = angular.element('<li active><a ng-href="#/foo">Foo</a></li>');
        element = compile(element)(scope);

        // Broadcast location change; the directive waits for this signal
        rootScope.$broadcast('$routeChangeSuccess');

        // Flush timeout so we don't have to write asynchronous tests.
        // The directive defers any action using a timeout so that other
        // directives it might depend on, such as ng-href, are evaluated
        // beforehand.
        timeout.flush();
      });

      it('also works with ng-href', function () {
        expect(element.hasClass('active')).toBeTruthy();
      });
    });
  });

  describe('with an inactive link', function () {
    beforeEach(function () {
      // Trigger location change
      location.path('/bar');

      // Create and compile element with directive; note that the link
      // is the NOT same as the current location after the location change.
      element = angular.element('<li active><a href="#/foo">Foo</a></li>');
      element = compile(element)(scope);

      // Broadcast location change; the directive waits for this signal
      rootScope.$broadcast('$routeChangeSuccess');

      // Flush timeout so we don't have to write asynchronous tests.
      // The directive defers any action using a timeout so that other
      // directives it might depend on, such as ng-href, are evaluated
      // beforehand.
      timeout.flush();
    });

    it('does not add the class "active" to the li', function () {
      expect(element.hasClass('active')).not.toBeTruthy();
    });
  });

  describe('with a formerly active link', function () {
    beforeEach(function () {
      // Trigger location change
      location.path('/bar');

      // Create and compile element with directive; note that the link
      // is the same as the current location after the location change.
      // Also not that the li element already has the class "active".
      // This is to make sure that a link that is active right now will
      // not be active anymore when the user navigates somewhere else.
      element = angular.element('<li class="active" active><a href="#/foo">Foo</a></li>');
      element = compile(element)(scope);

      // Broadcast location change; the directive waits for this signal
      rootScope.$broadcast('$routeChangeSuccess');

      // Flush timeout so we don't have to write asynchronous tests.
      // The directive defers any action using a timeout so that other
      // directives it might depend on, such as ng-href, are evaluated
      // beforehand.
      timeout.flush();
    });

    it('removes the "active" class from the li', function () {
      expect(element.hasClass('active')).not.toBeTruthy();
    });
  });
});
0
répondu weltschmerz 2015-07-08 01:20:16

de La route:

$routeProvider.when('/Account/', { templateUrl: '/Home/Account', controller: 'HomeController' });

le menu html:

<li id="liInicio" ng-class="{'active':url=='account'}">

le contrôleur:

angular.module('Home').controller('HomeController', function ($scope, $http, $location) {
    $scope.url = $location.url().replace(/\//g, "").toLowerCase();
...

le problème que j'ai trouvé ici est que l'élément du menu n'est actif que lorsque la page entière est chargée. Lorsque la vue partielle est chargée, le menu ne change pas. Quelqu'un sait pourquoi ça arrive?

0
répondu Dago MX 2015-09-10 15:46:45

Voici une bien meilleure façon de le faire

<ul>
    <li ng-class="{ active: isActive('/tasks')}"><a href="/">Tasks</a></li>
</ul>

function tasksController($scope, $location) 
{ 
    $scope.isActive = function (viewLocation) { 
        return viewLocation === $location.path();
    };
}
0
répondu Oluwaseye 2016-01-08 17:01:26
$scope.getClass = function (path) {
return String(($location.absUrl().split('?')[0]).indexOf(path)) > -1 ? 'active' : ''
}


<li class="listing-head" ng-class="getClass('/v/bookings')"><a href="/v/bookings">MY BOOKING</a></li>
<li class="listing-head" ng-class="getClass('/v/fleets')"><a href="/v/fleets">MY FLEET</a></li>
<li class="listing-head" ng-class="getClass('/v/adddriver')"><a href="/v/adddriver">ADD DRIVER</a></li>
<li class="listing-head" ng-class="getClass('/v/bookings')"><a href="/v/invoice">INVOICE</a></li>
<li class="listing-head" ng-class="getClass('/v/profile')"><a href="/v/profile">MY PROFILE</a></li>
<li class="listing-head"><a href="/v/logout">LOG OUT</a></li>
0
répondu Ashish Gupta 2016-08-06 09:00:22

j'ai trouvé la solution la plus facile. juste pour comparer indexOf en HTML

var myApp = angulaire.module ('myApp', []);

myApp.run(function($rootScope) {
    $rootScope.$on("$locationChangeStart", function(event, next, current) { 
         $rootScope.isCurrentPath = $location.path();  
    });
});



<li class="{{isCurrentPath.indexOf('help')>-1 ? 'active' : '' }}">
<a href="/#/help/">
          Help
        </a>
</li>
0
répondu NishantVerma.Me 2017-04-04 18:21:00