Come impostare la classe attiva navst bootstrap con Angular JS?


306

Se ho una barra di navigazione nel bootstrap con gli articoli

Home | About | Contact

Come posso impostare la classe attiva per ciascuna voce di menu quando sono attivi? Cioè, come posso impostare class="active"quando il percorso angolare è a

  1. #/ per Casa
  2. #/about per la pagina di informazioni
  3. #/contact per la pagina dei contatti


10
Questo è simile, ma non è un "modo angolare" per evidenziare i pulsanti di navigazione.
user1876508,


Se si utilizza il routing angolare , tenere presente che la risposta perfetta è nascosta in basso: stackoverflow.com/a/43822400/474189 .
Duncan Jones,

Risposte:


598

Un modo molto elegante è usare ng-controller per eseguire un singolo controller al di fuori di 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>

e includi in controllers.js:

function HeaderController($scope, $location) 
{ 
    $scope.isActive = function (viewLocation) { 
        return viewLocation === $location.path();
    };
}

10
Dato che sono nuovo a questo, apprezzerei se tu potessi fornire un esempio su come inserirlo in una direttiva header, per favore.
mono68,

41
Suggerirei return $location.path().indexOf(viewLocation) == 0;invece di utilizzare in modo da poter catturare anche le pagine con parametri
Sven Hecht,

7
Questo porta a termine il lavoro, ma difficilmente elegant- il nome della rotta, ad esempio, /dogsdeve essere duplicato nella chiamata aisActive('/dogs')
wal

7
Se si utilizza il router UI, è possibile utilizzare le ui-sref-active/ui-sref-active-eqdirettive, ad es. ui-sref-active-eq='active'o ui-sref-active='active'per ottenere gli stessi risultati
Dan Pantry,

10
@SvenHecht La preoccupazione per quella logica è che un link alla home page (/) corrisponderebbe a ogni altro percorso.
mwotton,

51

Ho appena scritto una direttiva per gestirlo, quindi puoi semplicemente aggiungere l'attributo all'elemento bs-active-linkgenitore <ul>e ogni volta che il percorso è cambiato, troverà il collegamento corrispondente e aggiungerà la activeclasse alla corrispondente <li>.

Puoi vederlo in azione qui: http://jsfiddle.net/8mcedv3b/

HTML di esempio:

<ul class="nav navbar-nav" bs-active-link>
  <li><a href="/home">Home</a></li>
  <li><a href="/contact">Contact</a></li>
</ul>

Javascript:

angular.module('appName')
.directive('bsActiveLink', ['$location', function ($location) {
return {
    restrict: 'A', //use as attribute 
    replace: false,
    link: function (scope, elem) {
        //after the route has changed
        scope.$on("$routeChangeSuccess", function () {
            var hrefs = ['/#' + $location.path(),
                         '#' + $location.path(), //html5: false
                         $location.path()]; //html5: true
            angular.forEach(elem.find('a'), function (a) {
                a = angular.element(a);
                if (-1 !== hrefs.indexOf(a.attr('href'))) {
                    a.parent().addClass('active');
                } else {
                    a.parent().removeClass('active');   
                };
            });     
        });
    }
}
}]);

1
mi piace meglio della risposta accettata perché non c'è duplicazione dei dati di configurazione, cioè i percorsi stessi rimangono in un solo posto e questo funziona solo ..
Aaron Anodide

1
ha funzionato per me usando scope. $ watch ("$ routeChangeSuccess", function () {.... invece di scope. $ on ("$ routeChangeSuccess", function () {....
aemad

Ho dovuto modificarlo un po 'per i miei scopi, ma una risposta fantastica! Abbastanza facile da capire.
Tony Anziano,

38

Puoi dare un'occhiata a AngularStrap , la direttiva navbar sembra essere ciò che stai cercando:

https://github.com/mgcrea/angular-strap/blob/master/src/navbar/navbar.js

.directive('bsNavbar', function($location) {
  'use strict';

  return {
    restrict: 'A',
    link: function postLink(scope, element, attrs, controller) {
      // Watch for the $location
      scope.$watch(function() {
        return $location.path();
      }, function(newValue, oldValue) {

        $('li[data-match-route]', element).each(function(k, li) {
          var $li = angular.element(li),
            // data('match-rout') does not work with dynamic attributes
            pattern = $li.attr('data-match-route'),
            regexp = new RegExp('^' + pattern + '$', ['i']);

          if(regexp.test(newValue)) {
            $li.addClass('active');
          } else {
            $li.removeClass('active');
          }

        });
      });
    }
  };
});

Per utilizzare questa direttiva:

  1. Scarica AngularStrap da http://mgcrea.github.io/angular-strap/

  2. Includi lo script nella tua pagina dopo bootstrap.js:
    <script src="lib/angular-strap.js"></script>

  3. Aggiungi le direttive al tuo modulo:
    angular.module('myApp', ['$strap.directives'])

  4. Aggiungi la direttiva alla tua barra di navigazione:
    <div class="navbar" bs-navbar>

  5. Aggiungi regex su ogni elemento di navigazione:
    <li data-match-route="/about"><a href="#/about">About</a></li>


1
Grazie. Questo mi ha aiutato a fissare la mia direttiva (l'intuizione mancante per me era la scope.$watch)
Ngure Nyaga,

Perché la elementvariabile viene passata al selettore jquery? $('...', element)
Lucio,

@Lucio il metodo accetta 2 argomenti - jQuery (selettore, contesto) - il secondo argomento è passare il contesto del selettore, o elemento DOM padre o un altro oggetto jQuery stesso - leggi di più qui
CoderTR

Questo funziona perfettamente per me - ho dovuto comunque apportare una modifica, per mgcrea.github.io/angular-strap la direttiva da aggiungere al tuo modulo mgcrea.ngStrapnon lo è$strap.directives
Vixxd

33

Ecco un approccio semplice che funziona bene con Angular.

<ul class="nav navbar-nav">
    <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>

All'interno del controller AngularJS:

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

2
Bel approccio. L'ho modificato un po '- ho usato la direttiva ng-class (ng-class = {active: isActive (' / View1 ')}) e ho aggiornato la funzione isActive per restituire true / false invece del nome della classe stessa.
patelsan,

Ho copiato tutto come il tuo esempio e per me $ location.path () non ha funzionato ... è passato a $ location.url () e ha funzionato!
Paulo Oliveira,

14

Se lavori con il router angolare, la direttiva RouterLinkActive può essere utilizzata in modo davvero elegante:

<ul class="navbar-nav">
  <li class="nav-item"><a class="nav-link" routerLink="home" routerLinkActive="active">Home</a></li>
  <li class="nav-item"><a class="nav-link" routerLink="gallery" routerLinkActive="active">Gallery</a></li>
  <li class="nav-item"><a class="nav-link" routerLink="pricing" routerLinkActive="active">Prices</a></li>
  <li class="nav-item"><a class="nav-link" routerLink="contact" routerLinkActive="active">Contact</a></li>
</ul>

2
Penso che questa dovrebbe essere la risposta accettata (almeno per Angular 2+), perché implementare qualcosa è già implementato? Ma per Bootstrap 3.3 la activeclasse dovrebbe essere nel <li>(puoi mettere routerLinkActive con routerLink o il suo genitore)
PhoneixS

3
Nota: se lo usi /come home page, routerLinkActivelo considererai attivo per qualsiasi URL che inizia con /, ad esempio /foo/, /foo/barecc. Per corrispondere esattamente, è necessario routerLinkActive="active" [routerLinkActiveOptions]="{exact:true}".
Duncan Jones,

8

Innanzitutto, questo problema può essere risolto in molti modi. In questo modo potrebbe non essere il più elegante, ma funziona con certezza.

Ecco una soluzione semplice che dovresti essere in grado di aggiungere a qualsiasi progetto. Puoi semplicemente aggiungere un "pageKey" o qualche altra proprietà quando configuri il percorso che puoi usare per chiudere. Inoltre, è possibile implementare un listener sul metodo $ routeChangeSuccess dell'oggetto $ route per attendere il completamento corretto di una modifica della rotta.

Quando il gestore viene attivato, si ottiene la chiave di pagina e si utilizza quella chiave per individuare gli elementi che devono essere "ATTIVI" per questa pagina e si applica la classe ATTIVO.

Tieni presente che hai bisogno di un modo per rendere TUTTI gli elementi "ATTIVI". Come puoi vedere sto usando la classe .pageKey sui miei oggetti di navigazione per spegnerli tutti e sto usando .pageKey_ {PAGEKEY} per attivarli singolarmente. Commutandoli tutti in inattivi, sarebbe considerato un approccio ingenuo, potenzialmente si otterrebbero prestazioni migliori utilizzando il percorso precedente per rendere inattivi solo gli elementi attivi, oppure è possibile modificare il selettore jquery per selezionare solo gli elementi attivi da rendere inattivi. L'uso di jquery per selezionare tutti gli elementi attivi è probabilmente la soluzione migliore perché assicura che tutto venga ripulito per il percorso corrente in caso di eventuali bug CSS che potrebbero essere stati presenti sul percorso precedente.

Il che significherebbe cambiare questa riga di codice:

$(".pagekey").toggleClass("active", false);

a questo

$(".active").toggleClass("active", false);

Ecco un po 'di codice di esempio:

Data una barra di avvio di

<div class="navbar navbar-inverse">
    <div class="navbar-inner">
        <a class="brand" href="#">Title</a>
        <ul class="nav">
            <li><a href="#!/" class="pagekey pagekey_HOME">Home</a></li>
            <li><a href="#!/page1/create" class="pagekey pagekey_CREATE">Page 1 Create</a></li>
            <li><a href="#!/page1/edit/1" class="pagekey pagekey_EDIT">Page 1 Edit</a></li>
            <li><a href="#!/page1/published/1" class="pagekey pagekey_PUBLISH">Page 1 Published</a></li>
        </ul>
    </div>
</div>

E un modulo angolare e un controller come il seguente:

<script type="text/javascript">

    function Ctrl($scope, $http, $routeParams, $location, $route) {

    }



    angular.module('BookingFormBuilder', []).
        config(function ($routeProvider, $locationProvider) {
            $routeProvider.
                when('/', { 
                   template: 'I\'m on the home page', 
                   controller: Ctrl, 
                   pageKey: 'HOME' }).
                when('/page1/create', { 
                   template: 'I\'m on page 1 create', 
                   controller: Ctrl, 
                   pageKey: 'CREATE' }).
                when('/page1/edit/:id', { 
                   template: 'I\'m on page 1 edit {id}', 
                   controller: Ctrl, pageKey: 'EDIT' }).
                when('/page1/published/:id', { 
                   template: 'I\'m on page 1 publish {id}', 
                   controller: Ctrl, pageKey: 'PUBLISH' }).
                otherwise({ redirectTo: '/' });

            $locationProvider.hashPrefix("!");
        }).run(function ($rootScope, $http, $route) {

            $rootScope.$on("$routeChangeSuccess", 
                           function (angularEvent, 
                                     currentRoute,
                                     previousRoute) {

                var pageKey = currentRoute.pageKey;
                $(".pagekey").toggleClass("active", false);
                $(".pagekey_" + pageKey).toggleClass("active", true);
            });

        });

</script>

Devi scorrere verso destra per vedere i valori pageKey sui percorsi, questa è la chiave di tutta questa soluzione.
Mark At Ramp51,

16
Questo potrebbe funzionare, ma è contro il consiglio generale per le app Angular.js: in Angular dovresti astenersi dal fare confusione con il DOM usando jQuery; se devi toccare il DOM, scrivi una direttiva.
Paulo Scardine,

questo è perfetto, se la manipolazione del dom ti disturba, aggiungi semplicemente una direttiva su .navbar, aggiungi un evento $ broadcast in routechangesuccess, $ rootScope. $ broadcast ('routeChanged', current.pageKey); e poi catturalo sulla tua direttiva e fai le manipolazioni del dom lì
Irshu,

7

Si può effettivamente utilizzare angolare ui--utils ' ui-routedirettiva:

<a ui-route ng-href="/">Home</a>
<a ui-route ng-href="/about">About</a>
<a ui-route ng-href="/contact">Contact</a>

o:

Controller di intestazione

/**
 * Header controller
 */
angular.module('myApp')
  .controller('HeaderCtrl', function ($scope) {
    $scope.menuItems = [
      {
        name: 'Home',
        url:  '/',
        title: 'Go to homepage.'
      },
      {
        name:   'About',
        url:    '/about',
        title:  'Learn about the project.'
      },
      {
        name:   'Contact',
        url:    '/contact',
        title:  'Contact us.'
      }
    ];
  });

Pagina dell'indice

<!-- index.html: -->
<div class="header" ng-controller="HeaderCtrl">
  <ul class="nav navbar-nav navbar-right">
    <li ui-route="{{menuItem.url}}" ng-class="{active: $uiRoute}"
      ng-repeat="menuItem in menuItems">
      <a ng-href="#{{menuItem.url}}" title="{{menuItem.title}}">
        {{menuItem.name}}
      </a>
    </li>
  </ul>
</div>

Se stai usando ui-utils, potresti anche essere interessato a ui-router per la gestione di viste parziali / nidificate.


L'approccio ui-route è molto seducente, ma finora non sono riuscito a farlo funzionare sul progetto generato dal generatore angolare di Yeoman.
gabuzo,

@gabuzo: hai installato angular-ui-utils via bower?
Lèse majesté,

6

Trovo tutte queste risposte un po 'troppo complicate per me, scusa. Quindi ho creato una piccola direttiva che dovrebbe funzionare su base navbar:

app.directive('activeLink', function () {
    return {
        link: function (scope, element, attrs) {
            element.find('.nav a').on('click', function () {
                angular.element(this)
                    .parent().siblings('.active')
                    .removeClass('active');
                angular.element(this)
                    .parent()
                    .addClass('active');
            });
        }
    };
});

Uso:

<ul class="nav navbar-nav navbar-right" active-link>
    <li class="nav active"><a href="home">Home</a></li>
    <li class="nav"><a href="foo">Foo</a></li>
    <li class="nav"><a href="bar">Bar</a></li>
</ul>

Il metodo funziona solo dopo aver fatto clic su un collegamento nella barra di navigazione. Se inizi su un URL "Foo", inizialmente "Home" sarà ancora selezionato. ad es. a partire da localhost: 9000 / # / contact fa apparire la Home selezionata nella barra di navigazione.
Adam Plocher,

5

Uso la direttiva di classe ng con $ location per raggiungerla.

<ul class="nav">
<li data-ng-class="{active: ($location.path() == '/') }">
    <a href="#/">Carpeta Amarilla</a>
</li>
<li class="dropdown" data-ng-class="{active: ($location.path() == '/auditoria' || $location.path() == '/auditoria/todos') }">
    <a class="dropdown-toggle" data-toggle="dropdown" href="#">
        Auditoria
        <b class="caret"></b>
    </a>
    <ul class="dropdown-menu pull-right">
        <li data-ng-class="{active: ($location.path() == '/auditoria') }">
            <a href="#/auditoria">Por Legajo</a>
        </li>
        <li data-ng-class="{active: ($location.path() == '/auditoria/todos') }">
            <a href="#/auditoria/todos">General</a>
        </li>
    </ul>
</li>
</ul>

Richiede che la barra di navigazione sia all'interno di un controller principale con accesso al servizio $ location come questo:

bajasApp.controller('MenuCntl', ['$scope','$route', '$routeParams', '$location', 
   function MenuCntl($scope, $route, $routeParams, $location) {
   $scope.$route = $route;
   $scope.$location = $location;
   $scope.$routeParams = $routeParams;
}]);

4

È possibile ottenere questo con un condizionale in un'espressione angolare, come ad esempio:

<a href="#" class="{{ condition ? 'active' : '' }}">link</a>

Detto questo, trovo che una direttiva angolare sia il modo più "corretto" di farlo, anche se l'outsourcing di molta di questa mini-logica può in qualche modo inquinare la tua base di codice.

Durante lo sviluppo utilizzo condizionali per lo stile della GUI una volta ogni tanto, perché è un po 'più veloce della creazione di direttive. Non potrei dirti un'istanza in cui sono rimasti a lungo nella base di codice. Alla fine lo trasformo in una direttiva o trovo un modo migliore per risolvere il problema.


4

Se usi ui-router , il seguente esempio dovrebbe soddisfare le tue esigenze in base al commento di @ DanPantry sulla risposta accettata senza aggiungere alcun codice sul lato controller:

<div class="collapse navbar-collapse" ng-controller="HeaderController">
    <ul class="nav navbar-nav">
        <li ui-sref-active="active"><a ui-sref="app.home()" href="/">Home</a></li>
        <li ui-sref-active="active"><a ui-sref="app.dogs()" href="/dogs">Dogs</a></li>
        <li ui-sref-active="active"><a ui-sref="app.cats()" href="/cats">Cats</a></li>
    </ul>
</div>
<div ng-view></div>

Puoi consultare i documenti per ulteriori informazioni.


Perfetto! sicuramente la soluzione più pulita
Aryeh Beitz,

semplicemente la soluzione migliore. chi non usa ui.router!
Rugiada

3

Se preferisci non utilizzare AngularStrap, questa direttiva dovrebbe fare il trucco !. Questa è una modifica di https://stackoverflow.com/a/16231859/910764 .

JavaScript

angular.module('myApp').directive('bsNavbar', ['$location', function ($location) {
  return {
    restrict: 'A',
    link: function postLink(scope, element) {
      scope.$watch(function () {
        return $location.path();
      }, function (path) {
        angular.forEach(element.children(), (function (li) {
          var $li = angular.element(li),
            regex = new RegExp('^' + $li.attr('data-match-route') + '$', 'i'),
            isActive = regex.test(path);
          $li.toggleClass('active', isActive);
        }));
      });
    }
  };
}]);

HTML

<ul class="nav navbar-nav" bs-navbar>
  <li data-match-route="/home"><a href="#/home">Home</a></li>
  <li data-match-route="/about"><a href="#/about">About</a></li>
</ul>

Nota: le classi HTML sopra riportate presuppongono che si stia utilizzando Bootstrap 3.x


3

Ecco la mia opinione su di esso. Un po 'di una combinazione di risposte trovate in questo post. Ho avuto un caso leggermente diverso, quindi la mia soluzione consiste nel separare il menu nel suo modello da utilizzare all'interno dell'Ojbect di definizione della direttiva, quindi aggiungere la barra di navigazione alla pagina in cui avevo bisogno. Fondamentalmente, avevo una pagina di accesso su cui non volevo includere il mio menu, quindi ho usato ngInclude e ho inserito questa direttiva quando ho effettuato l'accesso:

DIRETTIVA:

module.directive('compModal', function(){


return {
    restrict: 'E',
    replace: true,
    transclude: true,
    scope: true,
    templateUrl: 'templates/menu.html',
    controller: function($scope, $element, $location){
        $scope.isActive = function(viewLocation){

            var active = false;

            if(viewLocation === $location.path()){
                active = true;
            }

            return active;

        }
    }
 }
});

MODELLO DIRECTIVE (templates / menu.html)

<ul class="nav navbar-nav">
  <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>

HTML CHE COMPRENDE LA DIRETTIVA

<comp-navbar/>

Spero che questo ti aiuti


1
La funzione può essere abbreviata in solo $ scope.isActive = function (viewLocation) {return viewLocation === $ location.path (); };
WP McNeill,

2

Estendendo la mia risposta, ne avevo bisogno per gestire una struttura come questa.

-indice

-events <-active
--- lista
-eventi --- modifica-evento
--- eventi --- mappa eventi <-clicked

-places
--- place-list
--- place-edit
--- place-map

così invece di abbinare, ho dovuto usare indexOf, al fine di convalidare i collegamenti figlio che sono formattati per corrispondere alla condizione. Quindi per "eventi":

<li ng-class="{ active: isActive('/event')}" class="divider-vertical dropdown">


function NavController($scope, $location) { 
$scope.isActive = function (viewLocation) {
    var s=false;
    if($location.path().indexOf(viewLocation) != -1){
     s = true;
    }
    return s;
};}

2

Questa è una soluzione semplice

<ul class="nav navbar-nav navbar-right navbar-default menu">
  <li ng-class="menuIndice == 1 ? 'active':''">
    <a ng-click="menuIndice = 1" href="#/item1">item1</a>
  </li>
  <li ng-class="menuIndice == 2 ? 'active':''">
    <a ng-click="menuIndice = 2" href="#/item2">item2</a>
  </li>
  <li ng-class="menuIndice == 3 ? 'active':''">
    <a ng-click="menuIndice = 3" href="#/item3">item3</a>
  </li>
</ul>

1

In collaborazione con la risposta AngularStrap di @ Olivier, ho anche implementato la risposta di kevinknelson da: https://github.com/twbs/bootstrap/issues/9013 .

Nativamente, la barra di navigazione Bootstrap3 non è stata progettata per un'applicazione a pagina singola (ad es. Angolare) e quindi il menu quando su un piccolo schermo non stava crollando al clic.


1

JavaScript

/**
 * Main AngularJS Web Application
 */

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


/**
 * Setup Main Menu
 */

app.controller('MainNavCtrl', [ '$scope', '$location', function ( $scope, $location) {
    $scope.menuItems = [
        {
            name: 'Home',
            url:  '/home',
            title: 'Welcome to our Website'
        },
        {
            name: 'ABOUT',
            url:  '/about',
            title: 'Know about our work culture'
        },
        {
            name:   'CONTACT',
            url:    '/contact',
            title:  'Get in touch with us'
        }
    ];

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

HTML

  <div class="navbar-collapse collapse" ng-controller="MainNavCtrl">
    <ul id="add-magic-line" class="nav navbar-nav navbar-right">
      <li data-ng-class="{current_page_item: isActive('{{ menuItem.url }}')}" data-ng-repeat="menuItem in menuItems">
        <a data-ng-href="#{{menuItem.url}}" title="{{menuItem.title}}">
          {{menuItem.name}}
        </a>
      </li>
    </ul>
  </div>

Questo non funziona - non aggiunge la classe corrente al DOM
TheBlackBenzKid

1

Grazie a @Pylinux . Ho usato la sua tecnica e l'ho anche modificata per supportare "un" livello di menu a discesa (sub ul / li), poiché è quello di cui avevo bisogno. Guardalo in azione nel link violino qui sotto.

Fiddle aggiornato basato sulla risposta di pylinux - http://jsfiddle.net/abhatia/en4qxw6g/

Ho apportato le seguenti tre modifiche, al fine di supportare un menu a discesa di livello:
1. Aggiunto un valore di classe di dd (menu a discesa) per "un" elemento sotto li che deve avere un elenco secondario.

         <li><a class="dd">This link points to #/fun5</a>
          <ul>
            <li><a href="#/fun6?some=data">This link points to #/fun6</a>
            </li>
            <li><a href="#/fun7?some=data">This link points to #/fun7</a>
            </li>
            <li><a href="#/fun8?some=data">This link points to #/fun8</a>
            </li>
            <li><a href="#/fun9?some=data">This link points to #/fun9</a>
            </li>
          </ul>
        </li>


2. Aggiornato Javascript per aggiungere la seguente nuova logica.

 if(angular.element(li).parent().parent().children('a').hasClass("dd"))
 {angular.element(li).parent().parent().children('a.dd').addClass('active');}


3. CSS aggiornato per aggiungere quanto segue:

a.active {background-color:red;}

Speriamo che questo sia utile a qualcuno che cerca di implementare un menu a discesa a livello singolo.


1

Utilizzare un oggetto come variabile switch.
Puoi farlo in linea abbastanza semplicemente con:

<ul class="nav navbar-nav">
   <li ng-class="{'active':switch.linkOne}" ng-click="switch = {linkOne: true}"><a href="/">Link One</a></li>
   <li ng-class="{'active':switch.linkTwo}" ng-click="switch = {link-two: true}"><a href="/link-two">Link Two</a></li>
</ul>

Ogni volta che si fa clic su un collegamento, l'oggetto switch viene sostituito da un nuovo oggetto in cui è vera solo la proprietà dell'oggetto switch corretta. Le proprietà non definite verranno valutate come false e pertanto agli elementi che dipendono da esse non verrà assegnata la classe attiva.



0

Suggerisco di usare una direttiva su un collegamento. Ecco il violino.

Ma non è ancora perfetto. Fai attenzione agli hashbang;)

Ecco il javascript per direttiva:

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

ed ecco come sarebbe usato in 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>

successivamente styling con css:

.active{ color:red; }

0

Solo per aggiungere i miei due centesimi al dibattito, ho creato un modulo angolare puro (senza jquery) e funzionerà anche con gli hash url contenenti dati. ( ig #/this/is/path?this=is&some=data )

È sufficiente aggiungere il modulo come dipendenza e auto-activea uno degli antenati del menu. Come questo:

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

E il modulo è simile al seguente:

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

* (Ovviamente puoi semplicemente usare la parte direttiva)

** Vale anche la pena notare che questo non funziona per gli hash vuoti ( ig example.com/# o semplicemente example.com) che deve avere almeno example.com/#/o solo example.com#/. Ma questo succede automaticamente con ngResource e simili.


È semplicemente brutto. Il motivo per usare Angular è per semplicità.
Tom Stickel,

0

Questo ha fatto il trucco per me:

  var domain = '{{ DOMAIN }}'; // www.example.com or dev.example.com
  var domain_index =  window.location.href.indexOf(domain);
  var long_app_name = window.location.href.slice(domain_index+domain.length+1); 
  // this turns http://www.example.com/whatever/whatever to whatever/whatever
  app_name = long_app_name.slice(0, long_app_name.indexOf('/')); 
  //now you are left off with just the first whatever which is usually your app name

quindi usi jquery (funziona anche con angolare) per aggiungere la classe attiva

$('nav a[href*="' + app_name+'"]').closest('li').addClass('active');

e ovviamente il css:

.active{background:red;}

funziona se hai il tuo html in questo modo:

<ul><li><a href="/ee">ee</a></li><li><a href="/dd">dd</a></li></ul>

questo aggiungerà atumicamente la classe attiva usando l'url della pagina e colora il tuo sfondo in rosso se sei su www.somesite.com/ee thaen ee è l'app e sarà attiva


0

Questa è una risposta a lungo ma ho pensato di condividere la mia strada:

.run(function($rootScope, $state){
 $rootScope.$state = $state;
});

Modello:

<ul class="nav navbar-nav">
    <li ng-class="{ active: $state.contains('View1') }"><a href="...">View 1</a></li>
    <li ng-class="{ active: $state.contains('View2') }"><a href="...">View 2</a></li>
    <li ng-class="{ active: $state.contains('View3') }"><a href="...">View 3</a></li>
</ul>

Per coloro che utilizzano ui-router:

<ul class="nav navbar-nav">
        <li ui-sref-active="active"><a href="...">View 1</a></li>
        <li ui-sref-active="active"><a href="...">View 2</a></li>
        <li ui-sref-active="active"><a href="...">View 3</a></li>
</ul>

Per una corrispondenza esatta (ad es. Stati nidificati?) Utilizzare $state.name === 'full/path/to/state'oui-sref-active-eq="active"


0

Ecco un'altra soluzione per chiunque possa essere interessato. Il vantaggio di questo è che ha meno dipendenze. Diamine, funziona anche senza un server web. Quindi è completamente lato client.

HTML:

<nav class="navbar navbar-inverse" ng-controller="topNavBarCtrl"">
<div class="container-fluid">
    <div class="navbar-header">
        <a class="navbar-brand" href="#"><span class="glyphicon glyphicon-home" aria-hidden="true"></span></a>
    </div>
    <ul class="nav navbar-nav">
        <li ng-click="selectTab()" ng-class="getTabClass()"><a href="#">Home</a></li>
        <li ng-repeat="tab in tabs" ng-click="selectTab(tab)" ng-class="getTabClass(tab)"><a href="#">{{ tab }}</a></li>
    </ul>
</div>

Spiegazione:

Qui stiamo generando i collegamenti in modo dinamico da un modello angularjs usando la direttiva ng-repeat. La magia accade con i metodi selectTab()e getTabClass()definiti nel controller per questa barra di navigazione presentata di seguito.

controller:

angular.module("app.NavigationControllersModule", [])

// Constant named 'activeTab' holding the value 'active'. We will use this to set the class name of the <li> element that is selected.
.constant("activeTab", "active")

.controller("topNavBarCtrl", function($scope, activeTab){
    // Model used for the ng-repeat directive in the template.
    $scope.tabs = ["Page 1", "Page 2", "Page 3"];

    var selectedTab = null;

    // Sets the selectedTab.
    $scope.selectTab = function(newTab){
       selectedTab = newTab;
    };

    // Sets class of the selectedTab to 'active'.
    $scope.getTabClass = function(tab){
       return selectedTab == tab ? activeTab : "";
    };
});

Spiegazione:

selectTab()il metodo viene chiamato utilizzando la ng-clickdirettiva. Pertanto, quando si fa clic sul collegamento, la variabile selectedTabviene impostata sul nome di questo collegamento. Nell'HTML puoi vedere che questo metodo viene chiamato senza alcun argomento per la scheda Home in modo che venga evidenziato quando la pagina viene caricata.

Il getTabClass()metodo viene chiamato tramite ng-classdirettiva nell'HTML. Questo metodo controlla se la scheda in cui si trova è uguale al valore della selectedTabvariabile. Se vero, restituisce "attivo" altrimenti restituisce "" che viene applicato come nome della classe dalla ng-classdirettiva. Quindi qualsiasi CSS che hai applicato alla classe activeverrà applicato alla scheda selezionata.


Che cosa succede è che cerco un'altra scheda con qualsiasi altro mezzo?
Miguel Carvajal,

Cosa intendi?
Kovac,

ad esempio un collegamento nella pagina che porta a un'altra pagina all'interno di un'altra scheda. Ha senso?
Miguel Carvajal,

In quel caso penso che sia meglio usare ui-router come suggerito da Muli Yulzary nella risposta sopra. ui-router assegna uno stato a ciascun url. Quindi, una volta che qualcuno fa clic sul collegamento, l'utente verrà indirizzato a quel collegamento e lo stato dell'app angolare verrà aggiornato. Quindi ui-sref = "active" evidenzierà la scheda. Ecco la documentazione per angular 2: ui-router.github.io/ng2 . Inoltre, invece di utilizzare il normale bootstrap, guarda l'interfaccia utente Bootstrap fatta per l'uso con le app Angular. UI Bootstrap: angular-ui.github.io/bootstrap
kovac

0

Devi solo aggiungere la activeclasse richiesta con il codice colore richiesto.

Ex: ng-class="{'active': currentNavSelected}" ng-click="setNav"

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.