Wie setze ich die aktive Klasse der Bootstrap-Navigationsleiste mit Angular JS?


306

Wenn ich eine Navigationsleiste im Bootstrap mit den Elementen habe

Home | About | Contact

Wie lege ich die aktive Klasse für jeden Menüpunkt fest, wenn sie aktiv sind? Das heißt, wie kann ich einstellen, class="active"wann die Winkelroute ist

  1. #/ für Zuhause
  2. #/about für die About-Seite
  3. #/contact für die Kontaktseite


10
Dies ist ähnlich, aber keine "eckige Methode" zum Hervorheben der Navigationsschaltflächen.
user1876508

Mögliches Duplikat von Set Active Tab Style mit AngularJS
Amit G

Wenn Sie Angular Routing verwenden , beachten Sie bitte, dass die perfekte Antwort unten vergraben ist: stackoverflow.com/a/43822400/474189 .
Duncan Jones

Antworten:


598

Eine sehr elegante Möglichkeit besteht darin, mit ng-controller einen einzelnen Controller außerhalb der ng-Ansicht auszuführen:

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

und in controller.js aufnehmen:

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

10
Da ich neu in diesem Bereich bin, würde ich mich freuen, wenn Sie uns ein Beispiel geben könnten, wie dies in eine Header-Direktive eingefügt werden kann.
Mono68

41
Ich würde vorschlagen, return $location.path().indexOf(viewLocation) == 0;stattdessen zu verwenden, damit Sie auch Seiten mit Parametern abfangen können
Sven Hecht

7
Dies erledigt die Arbeit, aber es ist kaum elegant- der Routenname muss zB /dogsim Aufruf anisActive('/dogs')
wal

7
Wenn Sie UI Router verwenden, können Sie die ui-sref-active/ui-sref-active-eqAnweisungen verwenden, dh. ui-sref-active-eq='active'oder ui-sref-active='active'um die gleichen Ergebnisse zu erzielen
Dan Pantry

10
@SvenHecht Das Problem mit dieser Logik ist, dass ein Homepage-Link (/) mit jedem anderen Pfad übereinstimmt.
Mwotton

51

Ich habe gerade eine Anweisung geschrieben, um dies zu handhaben, sodass Sie das Attribut einfach bs-active-linkzum übergeordneten <ul>Element hinzufügen können. Jedes Mal, wenn sich die Route ändert, wird der passende Link gefunden und die activeKlasse zum entsprechenden hinzugefügt <li>.

Sie können es hier in Aktion sehen: http://jsfiddle.net/8mcedv3b/

Beispiel HTML:

<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
Ich mag dies besser als die akzeptierte Antwort, weil es keine Duplizierung von Konfigurationsdaten gibt, dh die Routen selbst bleiben an nur einem Ort und dies funktioniert einfach.
Aaron Anodide

1
arbeitete für mich mit scope. $ watch ("$ routeChangeSuccess", function () {.... anstelle von scope. $ on ("$ routeChangeSuccess", function () {....
aemad

Musste dies ein wenig für meine eigenen Zwecke optimieren, aber tolle Antwort! Leicht zu verstehen.
Tony Anziano

38

Sie können sich AngularStrap ansehen . Die Navbar-Direktive scheint genau das zu sein, wonach Sie suchen:

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

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

So verwenden Sie diese Richtlinie:

  1. Laden Sie AngularStrap von http://mgcrea.github.io/angular-strap/ herunter.

  2. Fügen Sie das Skript nach bootstrap.js in Ihre Seite ein:
    <script src="lib/angular-strap.js"></script>

  3. Fügen Sie die Anweisungen zu Ihrem Modul hinzu:
    angular.module('myApp', ['$strap.directives'])

  4. Fügen Sie die Direktive zu Ihrer Navigationsleiste hinzu:
    <div class="navbar" bs-navbar>

  5. Fügen Sie jedem Navigationselement reguläre Ausdrücke hinzu:
    <li data-match-route="/about"><a href="#/about">About</a></li>


1
Vielen Dank. Dies half mir, meine eigene Anweisung zu scope.$watch
korrigieren

Warum ist der element Variable an den jquery-Selektor übergeben? $('...', element)
Lucio

@Lucio Die Methode akzeptiert 2 Argumente - jQuery (Selektor, Kontext) - das zweite Argument besteht darin, den Kontext des Selektors zu übergeben, entweder das übergeordnete DOM-Element oder ein anderes jQuery-Objekt selbst - lesen Sie hier mehr
CoderTR

Das funktioniert perfekt für mich - ich musste jedoch eine Änderung pro vornehmen mgcrea.github.io/angular-strap ist die Anweisung, die zu Ihrem Modul mgcrea.ngStrap$strap.directives
hinzugefügt

33

Hier ist ein einfacher Ansatz, der gut mit Angular funktioniert.

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

In Ihrem AngularJS-Controller:

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

2
Netter Ansatz. Ich habe es ein wenig modifiziert - die ng-class-Direktive (ng-class = {active: isActive ('/ View1')}) verwendet und die isActive-Funktion aktualisiert, um true / false anstelle des Klassennamens selbst zurückzugeben.
Patelsan

Ich habe alles wie Ihr Beispiel kopiert und für mich hat $ location.path () nicht funktioniert ... auf $ location.url () umgestellt, und es hat funktioniert!
Paulo Oliveira

14

Wenn Sie mit einem Angular-Router arbeiten, kann die RouterLinkActive-Direktive sehr elegant verwendet werden:

<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
Ich denke, dies sollte die akzeptierte Antwort sein (zumindest für Winkel 2+). Warum ist etwas implementiert, das bereits implementiert ist? Aber für Bootstrap 3.3 sollte die activeKlasse in der <li>(Sie können den routerLinkActive mit dem routerLink oder seinem übergeordneten
Element setzen

3
Hinweis: Wenn Sie /als Ihre Startseite, routerLinkActivewird diese aktiv für jede URL betrachten beginnend mit /, zum Beispiel /foo/, /foo/barusw. genau zu entsprechen, müssen Sie routerLinkActive="active" [routerLinkActiveOptions]="{exact:true}".
Duncan Jones

8

In erster Linie kann dieses Problem auf viele Arten gelöst werden. Dieser Weg ist vielleicht nicht der eleganteste, aber er funktioniert auf jeden Fall.

Hier ist eine einfache Lösung, die Sie jedem Projekt hinzufügen können sollten. Sie können einfach einen "pageKey" oder eine andere Eigenschaft hinzufügen, wenn Sie Ihre Route konfigurieren, die Sie zum Abmelden verwenden können. Darüber hinaus können Sie einen Listener für die $ routeChangeSuccess-Methode des $ route-Objekts implementieren, um auf den erfolgreichen Abschluss einer Routenänderung zu warten.

Wenn Ihr Handler ausgelöst wird, erhalten Sie den Seitenschlüssel und suchen mit diesem Schlüssel nach Elementen, die für diese Seite "AKTIV" sein müssen, und wenden die Klasse AKTIV an.

Denken Sie daran, dass Sie eine Möglichkeit benötigen, ALLE Elemente "IN AKTIV" zu machen. Wie Sie sehen können, verwende ich die .pageKey-Klasse für meine Navigationselemente, um sie alle auszuschalten, und ich verwende die .pageKey_ {PAGEKEY}, um sie einzeln einzuschalten. Wenn Sie alle auf inaktiv umschalten, wird dies als naiver Ansatz angesehen. Möglicherweise erzielen Sie eine bessere Leistung, wenn Sie die vorherige Route verwenden, um nur aktive Elemente inaktiv zu machen, oder Sie können die Auswahlabfrage so ändern, dass nur aktive Elemente ausgewählt werden, die inaktiv gemacht werden sollen. Die Verwendung von jquery zur Auswahl aller aktiven Elemente ist wahrscheinlich die beste Lösung, da dadurch sichergestellt wird, dass im Falle von CSS-Fehlern, die möglicherweise auf der vorherigen Route aufgetreten sind, alles für die aktuelle Route bereinigt wird.

Was bedeuten würde, diese Codezeile zu ändern:

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

zu diesem

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

Hier ist ein Beispielcode:

Gegeben eine Bootstrap Navbar von

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

Und ein Winkelmodul und eine Steuerung wie die folgende:

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

Sie müssen nach rechts scrollen, um die pageKey-Werte auf den Routen anzuzeigen. Dies ist der Schlüssel für diese gesamte Lösung.
Markieren Sie an der Rampe 51 am

16
Dies mag funktionieren, widerspricht jedoch den allgemeinen Ratschlägen für Angular.js-Apps: In Angular sollten Sie nicht mit jQuery mit dem DOM herumspielen. Wenn Sie das DOM berühren müssen, schreiben Sie eine Anweisung.
Paulo Scardine

Dies ist perfekt, wenn Sie die Dom-Manipulation stört. Fügen Sie einfach eine Anweisung in die .navbar ein und fügen Sie ein $ Broadcast-Ereignis in routechangesuccess hinzu, $ rootScope. $ Broadcast ('routeChanged', current.pageKey). und dann erfassen Sie es auf Ihrer Anweisung und führen Sie die Dom-Manipulationen dort durch
Irshu

7

Sie können tatsächlich nutzen Winkel-ui-utils " ui-routeRichtlinie:

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

oder:

Header Controller

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

Indexseite

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

Wenn Sie UI-Utils verwenden, interessieren Sie sich möglicherweise auch für UI-Router zum Verwalten von partiellen / verschachtelten Ansichten.


Der UI-Routen-Ansatz ist sehr verführerisch, aber bisher habe ich es nicht geschafft, ihn für das vom Yeoman-Winkelgenerator generierte Projekt zum Laufen zu bringen.
Gabuzo

@gabuzo: Hast du Angular-UI-Utils über Bower installiert?
Lèse Majesté

6

Ich finde all diese Antworten für mich etwas zu kompliziert, sorry. Deshalb habe ich eine kleine Direktive erstellt, die pro Navigationsleiste funktionieren soll:

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

Verwendungszweck:

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

Ihre Methode funktioniert erst, nachdem Sie auf einen Link in der Navigationsleiste geklickt haben. Wenn Sie mit einer URL beginnen, die "Foo" lautet, wird "Home" zunächst noch ausgewählt. zB ab localhost: 9000 / # / contact wird das Home in der Navigationsleiste ausgewählt angezeigt.
Adam Plocher

5

Ich verwende die Direktive der Klasse ng mit $ location, um dies zu erreichen.

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

Die Navigationsleiste muss sich in einem Hauptcontroller mit Zugriff auf den folgenden $ location-Dienst befinden:

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

4

Sie können dies mit einer Bedingung in einem Winkelausdruck erreichen, wie z.

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

Abgesehen davon finde ich, dass eine Winkelanweisung die "richtige" Methode ist, obwohl das Auslagern eines Großteils dieser Minilogik Ihre Codebasis etwas verschmutzen kann.

Während der Entwicklung verwende ich gelegentlich Bedingungen für das GUI-Styling, da dies etwas schneller ist als das Erstellen von Direktiven. Ich konnte Ihnen jedoch keinen Fall nennen, in dem sie tatsächlich lange in der Codebasis verblieben sind. Am Ende verwandle ich es entweder in eine Richtlinie oder finde einen besseren Weg, um das Problem zu lösen.


4

Wenn Sie einen UI-Router verwenden , sollte das folgende Beispiel Ihren Anforderungen entsprechen, basierend auf dem Kommentar von @ DanPantry zur akzeptierten Antwort, ohne einen Controller-seitigen Code hinzuzufügen:

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

Sie können die Dokumente für weitere Informationen überprüfen .


perfekt! sicherlich die sauberste Lösung
Aryeh Beitz

ganz einfach die beste Lösung. wer benutzt nicht ui.router!
Tau

3

Wenn Sie AngularStrap lieber nicht verwenden möchten, sollte diese Anweisung den Trick machen!. Dies ist eine Änderung von 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>

Hinweis: Die obigen HTML-Klassen setzen voraus, dass Sie Bootstrap 3.x verwenden


3

Hier ist meine Meinung dazu. Eine kleine Kombination von Antworten in diesem Beitrag. Ich hatte einen etwas anderen Fall, daher besteht meine Lösung darin, das Menü in eine eigene Vorlage zu unterteilen, die in der Direktive Definition Ojbect verwendet werden soll, und dann meine Navigationsleiste zu der Seite hinzuzufügen, auf der ich sie benötigt habe. Grundsätzlich hatte ich eine Anmeldeseite, auf der ich mein Menü nicht einfügen wollte, also habe ich ngInclude verwendet und diese Anweisung eingefügt, wenn ich angemeldet war:

RICHTLINIE:

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;

        }
    }
 }
});

DIRECTIVE TEMPLATE (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, DAS DIE RICHTLINIE ENTHÄLT

<comp-navbar/>

Hoffe das hilft


1
Die Funktion kann auf nur $ scope.isActive = function (viewLocation) gekürzt werden {return viewLocation === $ location.path (); };
WP McNeill

2

Um meine Antwort zu erweitern, brauchte ich dies, um mit einer solchen Struktur fertig zu werden.

-Index

-events <-active
--- event-list
--- event-edit
--- event-map <-clicked

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

Anstelle des Abgleichs musste ich indexOf verwenden, um untergeordnete Links zu validieren, die so formatiert sind, dass sie der Bedingung entsprechen. Also für 'Ereignisse':

<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

Dies ist eine einfache Lösung

<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 Verbindung mit der AngularStrap-Antwort von @ Olivier habe ich auch die Antwort von kevinknelson implementiert: https://github.com/twbs/bootstrap/issues/9013 .

Die Bootstrap3-Navigationsleiste wurde ursprünglich nicht für eine Anwendung mit nur einer Seite (z. B. Angular) entwickelt, und daher wurde das Menü auf einem kleinen Bildschirm beim Klicken nicht reduziert.


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>

Dies funktioniert nicht - es wird nicht die aktuelle Klasse zum DOM
hinzugefügt

1

Vielen Dank an @Pylinux . Ich habe seine Technik verwendet und sie auch modifiziert, um "eine" Ebene des Dropdown-Menüs (sub ul / li) zu unterstützen, da ich das brauchte. Sehen Sie es in Aktion im Geigen-Link unten.

Fiddle wurde basierend auf der Antwort von pylinux aktualisiert - http://jsfiddle.net/abhatia/en4qxw6g/

Ich habe die folgenden drei Änderungen vorgenommen, um ein Ebenen-Dropdown-Menü zu unterstützen:
1. Es wurde ein Klassenwert von dd (Dropdown) für "a" -Element unter li hinzugefügt, für das eine untergeordnete Liste erforderlich ist.

         <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. Javascript wurde aktualisiert, um die folgende neue Logik hinzuzufügen.

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


3. Aktualisiertes CSS, um Folgendes hinzuzufügen:

a.active {background-color:red;}

Hoffentlich ist dies hilfreich für jemanden, der ein einstufiges Dropdown-Menü implementieren möchte.


1

Verwenden Sie ein Objekt als Schaltvariable.
Sie können dies ganz einfach inline tun mit:

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

Jedes Mal, wenn Sie auf einen Link klicken, wird das Switch-Objekt durch ein neues Objekt ersetzt, bei dem nur die richtige Switch-Objekt-Eigenschaft wahr ist. Die undefinierten Eigenschaften werden als falsch ausgewertet, sodass den von ihnen abhängigen Elementen nicht die aktive Klasse zugewiesen wird.



0

Ich schlage vor, eine Direktive für einen Link zu verwenden. Hier ist die Geige.

Aber es ist noch nicht perfekt. Pass auf die Hashbangs auf;)

Hier ist das Javascript für die Direktive:

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

und hier ist, wie es in HTML verwendet werden würde:

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

danach Styling mit CSS:

.active{ color:red; }

0

Um meine zwei Cent in die Debatte einzubeziehen, habe ich ein reines Winkelmodul (keine Abfrage) erstellt, das auch mit Hash-URLs funktioniert, die Daten enthalten. ( ig #/this/is/path?this=is&some=data )

Sie fügen das Modul einfach als Abhängigkeit und auto-activezu einem der Vorfahren des Menüs hinzu. So was:

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

Und das Modul sieht so aus:

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

* (Sie können natürlich auch nur den Direktiventeil verwenden)

** Es ist auch erwähnenswert, dass dies nicht für leere Hashes ( ig example.com/# oder nur example.com) funktioniert , die mindestens example.com/#/oder nur vorhanden sein müssen example.com#/. Dies geschieht jedoch automatisch mit ngResource und dergleichen.


Das ist einfach böse. Grund für die Verwendung von Angular ist der Einfachheit halber.
Tom Stickel

0

Das hat den Trick für mich getan:

  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

Dann verwenden Sie jquery (funktioniert auch mit Angular), um eine aktive Klasse hinzuzufügen

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

und natürlich die css:

.active{background:red;}

Dies funktioniert, wenn Sie Ihr HTML wie folgt haben:

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

Dadurch wird die aktive Klasse mithilfe der Seiten-URL hinzugefügt und der Hintergrund rot gefärbt, wenn Sie unter www.somesite.com/ee thaen ee die 'App' haben und diese aktiv ist


0

Dies ist lange beantwortet, aber ich dachte, ich würde meinen Weg teilen:

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

Vorlage:

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

Für diejenigen, die verwenden 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>

Für eine genaue Übereinstimmung (z. B. verschachtelte Zustände?) Verwenden Sie $state.name === 'full/path/to/state'oderui-sref-active-eq="active"


0

Hier ist eine weitere Lösung für alle, die interessiert sein könnten. Dies hat den Vorteil, dass weniger Abhängigkeiten bestehen. Heck, es funktioniert auch ohne Webserver. Es ist also komplett clientseitig.

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>

Erläuterung:

Hier generieren wir die Links dynamisch aus einem Winkelmodell unter Verwendung der Direktive ng-repeat. Magie passiert mit den Methoden selectTab()undgetTabClass() in der Steuerung für diese navbar unten dargestellt definiert.

Regler:

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

Erläuterung:

selectTab()Methode wird mit ng-clickDirektive aufgerufen . Wenn Sie also auf den Link klicken, wird die Variable selectedTabauf den Namen dieses Links gesetzt. Im HTML-Code können Sie sehen, dass diese Methode ohne Argument für die Registerkarte "Startseite" aufgerufen wird, sodass sie beim Laden der Seite hervorgehoben wird.

Die getTabClass()Methode wird über die ng-classDirektive im HTML aufgerufen . Diese Methode prüft, ob die Registerkarte, in der sie sich befindet, mit dem Wert der selectedTabVariablen übereinstimmt. Wenn true, wird "active" zurückgegeben, andernfalls wird "" zurückgegeben, was von der ng-classDirektive als Klassenname angewendet wird . Dann wird das CSS, das Sie auf die Klasse activeangewendet haben, auf die ausgewählte Registerkarte angewendet.


Was passiert, ist, dass ich auf andere Weise zu einem anderen Tab navigiere?
Miguel Carvajal

Was meinst du?
Kovac

Zum Beispiel ein Link auf der Seite, der Sie zu einer anderen Seite führt, die sich auf einer anderen Registerkarte befindet. Macht Sinn?
Miguel Carvajal

In diesem Fall denke ich, dass es besser ist, einen UI-Router zu verwenden, wie von Muli Yulzary in der obigen Antwort vorgeschlagen. Der UI-Router weist jeder URL einen Status zu. Sobald jemand auf den Link klickt, wird der Benutzer zu diesem Link weitergeleitet und der Status der Winkel-App wird aktualisiert. Dann markiert ui-sref = "active" die Registerkarte. Hier ist die Dokumentation für Winkel 2: ui-router.github.io/ng2 . Anstatt den normalen Bootstrap zu verwenden, sehen Sie sich auch den UI-Bootstrap an, der für die Verwendung mit Angular-Apps erstellt wurde. UI Bootstrap: angle-ui.github.io/bootstrap
kovac

0

Sie müssen nur die erforderliche activeKlasse mit dem erforderlichen Farbcode hinzufügen .

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

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.