page navigationend cambiar angularjs

angularjs - navigationend - title angular 6



¿Cómo resaltar un elemento del menú actual? (30)

¿Ayuda AngularJS de alguna manera a establecer una clase active en el enlace de la página actual?

Me imagino que hay una forma mágica de hacerlo, pero parece que no puedo encontrarlo.

Mi menú se ve como:

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

y tengo controladores para cada uno de ellos en mis rutas: TasksController y ActionsController .

Pero no puedo encontrar una manera de enlazar la clase "activa" en los enlaces a los controladores.

¿Alguna pista?


Acabo de escribir una directiva para esto.

Uso:

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

Implementación:

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

Pruebas:

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


Aquí está la solución que se me ocurrió después de leer algunas de las excelentes sugerencias anteriores. En mi situación particular, estaba tratando de usar el componente de pestañas de Bootstrap como mi menú, pero no quería usar la versión de Angular-UI de esto porque quiero que las pestañas actúen como un menú, donde cada pestaña es capaz de marcar, en lugar de las pestañas que actúan como navegación para una sola página. (Consulte http://angular-ui.github.io/bootstrap/#/tabs si está interesado en cómo se ve la versión de UI Angular de las pestañas de bootstrap).

Realmente me gustó la respuesta de kfis sobre la creación de su propia directiva para manejar esto, sin embargo, me pareció incómodo tener una directiva que se debía colocar en cada enlace. Así que he creado mi propia directiva angular que se coloca en lugar de una vez en la ul . En caso de que alguien más esté tratando de hacer lo mismo, pensé que lo publicaría aquí, aunque como dije, muchas de las soluciones anteriores también funcionan. Esta es una solución un poco más compleja en lo que respecta a javascript, pero crea un componente reutilizable con un mínimo de marcado.

Aquí está el javascript para la directiva y el proveedor de ruta para 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"); }); } }; }]);

Entonces en tu html simplemente:

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

Aquí está el plunker para ello: http://plnkr.co/edit/xwGtGqrT7kWoCKnGDHYN?p=preview .


Aquí están mis dos centavos, esto funciona bien.

NOTA: Esto no coincide con las páginas infantiles (que es lo que necesitaba).

Ver:

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

Controlador:

// make sure you inject $location as a dependency $scope.isCurrentLocation = function(path){ return path === $location.path() }


Aquí hay otra directiva para resaltar los enlaces activos.

Características clave:

  • Funciona bien con href que contiene expresiones angulares dinámicas.
  • Compatible con navegación hash-bang
  • Compatible con Bootstrap, donde la clase activa debe aplicarse al padre, no al enlace en sí.
  • Permite activar el enlace si alguna ruta anidada está activa
  • Permite desactivar el enlace si no está activo.

Código:

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

Uso:

Ejemplo simple con expresión angular, digamos $ scope.var = 2 , entonces el enlace estará activo si la ubicación es / url / 2 :

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

Ejemplo de bootstrap, li padre obtendrá clase activa:

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

Ejemplo con urls anidadas, el enlace estará activo si alguna url anidada está activa (es decir, / url / 1 , / url / 2 , url / 1/2 / ... )

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

Ejemplo complejo, el enlace apunta a una url ( / url1 ) pero estará activo si se selecciona otra ( / url2 ):

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

Ejemplo con enlace deshabilitado, si no está activo tendrá una clase ''deshabilitada'' :

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

Todos los atributos de enlace activo se pueden usar en cualquier combinación, por lo que se podrían implementar condiciones muy complejas.


Aquí hay un enfoque simple que funciona bien con 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>

Dentro de su controlador AngularJS:

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

Este hilo tiene una serie de otras respuestas similares.

¿Cómo configurar la clase activa bootstrap navbar con Angular JS?


Aquí hay una extensión de la directiva kfis que hice para permitir diferentes niveles de coincidencia de ruta. Esencialmente, encontré la necesidad de hacer coincidir las rutas URL hasta una cierta profundidad, ya que la coincidencia exacta no permite el anidamiento y las redirecciones de estado predeterminadas. Espero que esto ayude.

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

Y aquí es cómo uso el enlace.

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

Esta directiva coincidirá con el nivel de profundidad especificado en el valor de atributo de la directiva. Solo significa que puede ser usado en otros lugares muchas veces.


De acuerdo con la respuesta de @kfis, sus comentarios, y mi recomendación, es la directiva final como se muestra a continuación:

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

Y aquí es cómo se usaría 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>

después de peinar con css:

.active { color: red; }


En mi caso resolví este problema creando un controlador simple responsable de la navegación.

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

Y simplemente agregando ng-class al elemento así:

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


Hay una directiva ng-class , que enlaza variables y clases css. También acepta el objeto (pares className vs bool value).

Aquí está el ejemplo, http://plnkr.co/edit/SWZAqj


La answer de @ Renan-tomal-fernandes es buena, pero necesitaba un par de mejoras para funcionar correctamente. Tal como estaba, siempre detectaría el enlace a la página de inicio (/) como activado, incluso si estuviera en otra sección.

Así que lo mejoré un poco, aquí está el código. Trabajo con Bootstrap por lo que la parte activa está en el elemento <li> lugar de la <a> .

Controlador

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

Modelo

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


Lo hice así:

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

Esto le permite tener enlaces en una sección que tiene directriz track-active:

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

Este enfoque me parece mucho más limpio que otros.

Además, si está usando jQuery, puede hacerlo mucho más limpio porque jQlite solo tiene soporte de selector básico. Una versión mucho más limpia con jQuery incluida antes de la inclusión angular se vería así:

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

Aquí hay un jsFiddle


Lo más importante para mí fue no cambiar todo el código predeterminado de bootstrap. Aquí es mi controlador de menú el que busca opciones de menú y luego agrega el comportamiento que queremos.

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>


Mi solución a este problema, use route.current en la plantilla angular.

Como tiene la ruta /tasks para resaltar en su menú, puede agregar su propio elemento de menú de propiedades a las rutas declaradas por su módulo:

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

Luego, en su plantilla tasks.html puede usar la siguiente directiva ng-class :

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

En mi opinión, esto es mucho más limpio que todas las soluciones propuestas.


Ninguna de las sugerencias de directivas anteriores me fue útil. Si tienes una barra de navegación de arranque como esta

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

(que podría ser un inicio $ yo angular ), entonces desea agregar .active a la lista de clases del elemento <li> , no al elemento en sí; es decir, <li class="active">..</li> . Así que escribí esto:

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

uso set-parent-active ; .active es el predeterminado por lo que no es necesario configurar

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

y el elemento principal <li> será .active cuando el enlace esté activo. Para usar una clase .active alternativa como .highlight , simplemente

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


Para aquellos que usan ui-router, mi respuesta es algo similar a la de Ender2050, pero prefiero hacer esto a través de pruebas de nombre de estado:

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

HTML correspondiente:

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


Para usuarios de AngularUI Router:

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

Y eso colocará una clase active en el objeto que se selecciona.


Puedes implementar esto muy simple, aquí hay un ejemplo:

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

Y su controlador debe ser esto:

app.controller("MenuCtrl", function($scope, $location) { $scope.menuClass = function(page) { var current = $location.path().substring(1); return page === current ? "active" : ""; }; });


Si desea que los enlaces para la directiva en un contenedor en lugar de seleccionar cada enlace individual (hace que sea más fácil ver el alcance en Batarang), esto también funciona bastante bien:

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

El marcado solo sería:

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

También debo mencionar que estoy usando jQuery ''full-fat'' en este ejemplo, pero puedes alterar fácilmente lo que he hecho con el filtrado y demás.


Solo para agregar mis dos centavos en el debate, he creado un módulo angular puro (no jQuery), y también funcionará con URL de hash que contienen datos. (por ejemplo, #/this/is/path?this=is&some=data )

Simplemente agregue el módulo como una dependencia y se auto-active a uno de los ancestros del menú. Me gusta esto:

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

Y el módulo se ve así:

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

(Por supuesto, puedes usar la parte directiva)

También vale la pena notar que esto no funciona para hashes vacíos (por ejemplo, example.com/# o solo example.com ) necesita tener al menos example.com/#/ o solo example.com#/ . Pero esto sucede automáticamente con ngResource y similares.

Y aquí está el violín: http://jsfiddle.net/gy2an/8/


Sugiero usar una directiva en un enlace.

Pero todavía no es perfecto. Cuidado con los hashbangs;)

Aquí está el javascript para la directiva:

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

Y aquí es cómo se usaría 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>

después de peinar con css:

.active { color: red; }


Tuve un problema similar con el menú ubicado fuera del alcance del controlador. No estoy seguro de si esta es la mejor solución o una recomendada, pero esto es lo que funcionó para mí. He añadido lo siguiente a la configuración de mi aplicación:

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

Luego en la vista tengo:

<li><a href="/" ng-class="{true: ''active''}[menuActive(''/'', true)]">Home</a></li> <li><a href="/register" ng-class="{true: ''active''}[menuActive(''/register'')]"> <li>...</li>


Usando una directiva (ya que estamos haciendo manipulación de DOM aquí), lo siguiente es probablemente lo más cercano a hacer las cosas a la "manera angular":

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

Entonces su HTML se vería así:

<ul class="dropdown-menu" filter="times"></ul>


a la vista

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

en el controlador

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

Con esto, el enlace de tareas tendrá la clase activa en cualquier URL que comience con ''/ tareas'' (por ejemplo, ''tareas / 1 / informes'')


tenia el mismo problema Aquí está mi 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'' ])



Usando Angular Version 6 con Bootstrap 4.1

Pude hacerlo como se ve a continuación.

En el siguiente ejemplo, cuando la URL ve ''/ contact'', el bootstrap active se agrega a la etiqueta html. Cuando la URL cambia se elimina.

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

Esta directiva le permite agregar una clase CSS a un elemento cuando la ruta del enlace se activa.

Lea más en el sitio web Angular


Aquí hay una manera mucho mejor de hacerlo.

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


La ruta:

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

El menú html:

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

El controlador:

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

El problema que encontré aquí es que el elemento del menú está activo solo cuando se carga la página completa. Cuando se carga la vista parcial, el menú no cambia. Alguien sabe por qué sucede?


Encontré la solución más fácil. Solo para comparar indexOf en HTML

var myApp = angular.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>


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