Legen Sie mit AngularJS den aktiven Registerkartenstil fest

144

Ich habe Routen in AngularJS wie folgt eingestellt:

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

Ich habe einige Links in der oberen Leiste, die als Registerkarten gestaltet sind. Wie kann ich einer Registerkarte abhängig von der aktuellen Vorlage oder URL eine aktive Klasse hinzufügen?

Sergei Basharov
quelle
4
@AminMeyghani Wie kann diese Frage ein Duplikat der Frage sein, die fast ein Jahr später gestellt wurde ?
Regent

Antworten:

274

Eine Möglichkeit, dies zu lösen, ohne sich auf URLs verlassen zu müssen, besteht darin, jedem Teil während der $routeProviderKonfiguration ein benutzerdefiniertes Attribut hinzuzufügen , wie folgt :

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

Belichten Sie $routein Ihrem Controller:

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

Legen Sie die activeKlasse basierend auf der aktuell aktiven Registerkarte fest:

<li ng-class="{active: $route.current.activetab == 'dashboard'}"></li>
<li ng-class="{active: $route.current.activetab == 'lab'}"></li>
Rob Juurlink
quelle
3
Dies ist die beste Lösung, die ich bisher gesehen habe, da sie dynamische URLs wie / foo /: bar unterstützt.
Martinpaulucci
3
Ich war tatsächlich nicht in der Lage, dies zum Laufen zu bringen. Könnten Sie eine plnkr zur Verfügung stellen?
PPPaul
9
Nur eins: Besser einstellen, $scope.activeTab = $route.current.activetabdamit Sie das HTML ein wenig sauberer halten können.
Christoph
2
Dies funktioniert in AngularJS 1.0.8 nicht. $ route.current ist undefiniert.
Wels
2
Kombinieren Sie dies mit dem folgenden $rootScopeTrick von @ Lucas , um ihn in allen Bereichen verfügbar zu machen.
Colllin
134

Eine Möglichkeit hierfür wäre die Verwendung der ngClass-Direktive und des $ location-Dienstes. In Ihrer Vorlage können Sie Folgendes tun:

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

Wo isActivewäre eine Funktion in einem so definierten Bereich:

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

Hier ist die komplette jsFiddle: http://jsfiddle.net/pkozlowski_opensource/KzAfG/

Das Wiederholen ng-class="{active:isActive('/dashboard')}"auf jeder Navigationsregisterkarte kann mühsam sein (wenn Sie viele Registerkarten haben), daher ist diese Logik möglicherweise ein Kandidat für eine sehr einfache Anweisung.

pkozlowski.opensource
quelle
1
Es hat lange gedauert, bis ich festgestellt habe, dass "sehr einfache Anweisungen" tatsächlich sehr einfach zu schreiben sind. Deshalb habe ich unten eine angegeben. :-) Es sollte in einer Vielzahl von Kontexten ohne nicht deklarative Konfiguration wiederverwendbar sein.
XML
1
Wie können Sie mit Blick auf die jsFiddle die aktuelle Seite beim Laden der Seite aktivieren? Das Beispiel funktioniert nur, wenn ein Benutzer auf eine Option klickt. Beispielsweise möchten Sie möglicherweise, dass ein "Home" -Navigation hervorgehoben wird, wenn Sie über einen externen Link auf der Homepage landen.
Thathurtabit
Ahh kratzte sich ein bisschen am Kopf. Vielen Dank!
Masterwok
41

Befolgen Sie die Empfehlungen von Pavel, eine benutzerdefinierte Direktive zu verwenden. Hier ist eine Version, bei der der routeConfig keine Nutzdaten hinzugefügt werden müssen. Sie ist sehr deklarativ und kann an jede Ebene des Pfads angepasst werden, indem Sie einfach ändern, auf welche slice()davon Sie achten .

app.directive('detectActiveTab', function ($location) {
    return {
      link: function postLink(scope, element, attrs) {
        scope.$on("$routeChangeSuccess", function (event, current, previous) {
            /*  
                Designed for full re-usability at any path, any level, by using 
                data from attrs. Declare like this: 
                <li class="nav_tab">
                  <a href="#/home" detect-active-tab="1">HOME</a>
                </li> 
            */

            // This var grabs the tab-level off the attribute, or defaults to 1
            var pathLevel = attrs.detectActiveTab || 1,
            // This var finds what the path is at the level specified
                pathToCheck = $location.path().split('/')[pathLevel] || 
                  "current $location.path doesn't reach this level",
            // This var finds grabs the same level of the href attribute
                tabLink = attrs.href.split('/')[pathLevel] || 
                  "href doesn't include this level";
            // Above, we use the logical 'or' operator to provide a default value
            // in cases where 'undefined' would otherwise be returned.
            // This prevents cases where undefined===undefined, 
            // possibly causing multiple tabs to be 'active'.

            // now compare the two:
            if (pathToCheck === tabLink) {
              element.addClass("active");
            }
            else {
              element.removeClass("active");
            }
        });
      }
    };
  });

Wir erreichen unsere Ziele, indem wir auf das $routeChangeSuccessEreignis hören, anstatt ein $watchauf den Weg zu bringen. Ich arbeite unter der Überzeugung, dass dies bedeutet, dass die Logik weniger häufig ausgeführt werden sollte, da ich denke, dass Uhren bei jedem $digestZyklus feuern .

Rufen Sie es auf, indem Sie Ihr Argument auf Pfadebene für die Direktivendeklaration übergeben. Dies gibt an, mit welchem ​​Teil des aktuellen $ location.path () Sie Ihr hrefAttribut abgleichen möchten .

<li class="nav_tab"><a href="#/home" detect-active-tab="1">HOME</a></li>

Wenn Ihre Registerkarten auf die Basisebene des Pfads reagieren sollen, geben Sie das Argument '1' ein. Wenn location.path () "/ home" ist, stimmt es mit dem "# / home" in der href. Wenn Sie Registerkarten haben, die auf die zweite oder dritte oder elfte Ebene des Pfads reagieren sollen, passen Sie sie entsprechend an. Dieses Schneiden von 1 oder höher umgeht das schändliche '#' in der href, das bei Index 0 leben wird.

Die einzige Voraussetzung ist, dass Sie ein aufrufen <a>, da das Element das Vorhandensein eines hrefAttributs voraussetzt , das mit dem aktuellen Pfad verglichen wird. Sie können sich jedoch relativ leicht anpassen, um ein übergeordnetes oder untergeordnetes Element zu lesen / schreiben, wenn Sie das <li>oder etwas aufrufen möchten. Ich grabe dies, weil Sie es in vielen Kontexten wiederverwenden können, indem Sie einfach das Argument pathLevel variieren. Wenn die zu lesende Tiefe in der Logik angenommen wurde, benötigen Sie mehrere Versionen der Direktive, um sie mit mehreren Teilen der Navigation zu verwenden.


EDIT 18.03.14: Die Lösung wurde nicht ausreichend verallgemeinert und wird aktiviert, wenn Sie ein Argument für den Wert von 'activeTab' definieren, das undefinedsowohl für beide $location.path()als auch für das Element zurückgegeben wird href. Weil : undefined === undefined. Aktualisiert, um diesen Zustand zu beheben.

Während ich daran arbeitete, wurde mir klar, dass es eine Version geben sollte, die Sie einfach für ein übergeordnetes Element deklarieren können, mit einer Vorlagenstruktur wie dieser:

<nav id="header_tabs" find-active-tab="1">
    <a href="#/home" class="nav_tab">HOME</a>
    <a href="#/finance" class="nav_tab">Finance</a>
    <a href="#/hr" class="nav_tab">Human Resources</a>
    <a href="#/quarterly" class="nav_tab">Quarterly</a>
</nav>

Beachten Sie, dass diese Version nicht mehr im entferntesten Stil HTML im Bootstrap-Stil ähnelt. Aber es ist moderner und verwendet weniger Elemente, also bin ich parteiisch. Diese Version der Direktive sowie das Original sind jetzt auf Github als Drop-In-Modul verfügbar, das Sie einfach als Abhängigkeit deklarieren können. Ich würde sie gerne bower-ize, wenn jemand sie tatsächlich benutzt.

Wenn Sie eine Bootstrap-kompatible Version wünschen, die <li>'s' enthält , können Sie auch das Angular-UI-Bootstrap-Tabs-Modul verwenden , das meiner Meinung nach nach diesem ursprünglichen Beitrag herausgekommen ist und das vielleicht sogar noch aussagekräftiger ist als dieses. Es ist weniger prägnant für grundlegende Dinge, bietet Ihnen jedoch einige zusätzliche Optionen, wie deaktivierte Registerkarten und deklarative Ereignisse, die beim Aktivieren und Deaktivieren ausgelöst werden.

XML
quelle
4
Ich konnte nicht glauben, dass niemand tatsächlich abstimmt! Hier sind meine 2 Cent. Obwohl der Code einen kleinen Fehler enthält, sollte die 'tabLevel' 'activeTab' sein. Und für den Bootstrap-Stil möchten Sie möglicherweise die 'aktive' Klasse anstelle des A-Elements zum LI-Element hinzufügen. Dies erfordert jedoch nur geringfügige Änderungen.
David Lin
1
Sie sind absolut korrekt in Bezug auf activeTab, @DavidLin. Bearbeitet. Aber ich bin nicht in die Struktur von Bootstrap verliebt, daher ein bewusster Unterschied. Tatsächlich fange ich an zu denken, dass Navigationsabstraktionen möglicherweise überhaupt nicht dazu gehören ulund vielleicht nur Sammlungen von Ankern sein sollten, die von einem navoder einem anderen Gruppierungselement umhüllt sind . Der Umgang mit der Zwischenschicht von li's ist eine zusätzliche Komplexität ohne Auszahlung, insbesondere jetzt, wo wir das navElement zur Verfügung haben, um klar zu machen, was los ist.
XML
Das ist einfach und genial. Ich war überrascht, dass es in Angular noch nicht so etwas gab, um die Route zu überprüfen, auf der Sie sich befinden.
Intellix
1
Damit es mit bootstrap3 funktioniert, müssen Sie lediglich "element.addClass (" active ");" in "element.parent (" li "). AddClass (" active ");" Ich denke, es könnte besser sein benannt, so etwas wie is-active-tab anstelle von active-tab, was zu deklarieren scheint, dass die Registerkarte aktiv ist. Ansonsten ist dies eine sehr nette Richtlinie. Siehe diese Änderung in der Antwort von @domi
Bootscoder
Beste Lösung auf dieser Seite, kann nicht glauben, dass es so wenig positive Stimmen gibt.
Karolis
27

@ rob-juurlink Ich habe deine Lösung ein bisschen verbessert:

anstelle jeder Route, die eine aktive Registerkarte benötigt; und ich muss die aktive Registerkarte in jedem Controller einstellen, um Folgendes zu tun:

var App = angular.module('App',[]);
App.config(['$routeProvider', function($routeProvider){
  $routeProvider.
  when('/dashboard', {
    templateUrl: 'partials/dashboard.html',
    controller: Ctrl1
  }).
  when('/lab', {
    templateUrl: 'partials/lab.html',
    controller: Ctrl2
  });
}]).run(['$rootScope', '$location', function($rootScope, $location){
   var path = function() { return $location.path();};
   $rootScope.$watch(path, function(newVal, oldVal){
     $rootScope.activetab = newVal;
   });
}]);

Und das HTML sieht so aus. Das Activetab ist nur die URL, die sich auf diese Route bezieht. Dadurch entfällt lediglich die Notwendigkeit, Code in jedem Controller hinzuzufügen (Ziehen von Abhängigkeiten wie $ route und $ rootScope, wenn dies der einzige Grund ist, warum sie verwendet werden).

<ul>
    <li ng-class="{active: activetab=='/dashboard'}">
       <a href="#/dashboard">dashboard</a>
    </li>
    <li ng-class="{active: activetab=='/lab'}">
       <a href="#/lab">lab</a>
    </li>
</ul>
Lucas
quelle
Vielen Dank für diese Änderung. Sehr schön. Haben Sie Vorschläge zum Festlegen einer aktiven Registerkarte beim ersten Laden der Seite?
Hairgami_Master
2
hängt davon ab, was Sie wollen. Normalerweise ist '/' url Ihr Hauptcontroller. Auf diese Weise lädt der Benutzer, wenn er zu Ihrer URL wechselt, diesen Controller und setzt diese Registerkarte als aktiv. Im obigen Beispiel habe ich keine '/' URL. Wenn dies der Fall ist, fügen Sie einfach einen .otherwise () $ routeProvider hinzu. when ('/ dashboard', {templateUrl: 'partials / dashboard.html', controller: Ctrl1}). when ('/ lab', {templateUrl: 'partials / lab.html', controller: Ctrl2}). else ({redirectTo: '/ dashboard'}); viel Glück!
Lucas
Vielen Dank @Lucas. Das hat geholfen. Aus irgendeinem Grund musste ich das Symbol # zu meiner Hauptroute hinzufügen, wenn ('# /', {controller: FormsController, templateUrl: 'partials / dashboard.html'}).
Hairgami_Master
Ich bevorzuge diesen Weg. Ein rootScope haben und alles tun, wo immer
wrivas
16

Vielleicht könnte eine solche Anweisung Ihr Problem lösen: http://jsfiddle.net/p3ZMR/4/

HTML

<div ng-app="link">
<a href="#/one" active-link="active">One</a>
<a href="#/two" active-link="active">One</a>
<a href="#" active-link="active">home</a>


</div>

JS

angular.module('link', []).
directive('activeLink', ['$location', function(location) {
    return {
        restrict: 'A',
        link: function(scope, element, attrs, controller) {
            var clazz = attrs.activeLink;
            var path = attrs.href;
            path = path.substring(1); //hack because path does bot return including hashbang
            scope.location = location;
            scope.$watch('location.path()', function(newPath) {
                if (path === newPath) {
                    element.addClass(clazz);
                } else {
                    element.removeClass(clazz);
                }
            });
        }

    };

}]);
kfis
quelle
1
Beachten Sie, dass Sie $ beobachten verwenden müssen, wenn die href einen Ausdruck enthält: docs.angularjs.org/guide/directive#Attributes . Siehe aktualisierte Geige: jsfiddle.net/p3ZMR/10
Narretz
14

Einfachste Lösung hier:

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

Welches ist:

Verwenden Sie ng-controller, um 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();
    };
}
Zymotik
quelle
2
stimmte zu, bei weitem am einfachsten
AngeloS
12

Ich empfehle die Verwendung des state.ui-Moduls, das nicht nur mehrere und verschachtelte Ansichten unterstützt, sondern auch diese Art der Arbeit sehr einfach macht (Code unten zitiert):

<ul class="nav">
    <li ng-class="{ active: $state.includes('contacts') }"><a href="#{{$state.href('contacts')}}">Contacts</a></li>
    <li ng-class="{ active: $state.includes('about') }"><a href="#{{$state.href('about')}}">About</a></li>
</ul>

Lesenswert.

David Lin
quelle
4

Hier ist eine weitere Version der LI-Änderung von XMLillies mit domi, bei der anstelle einer Pfadebene eine Suchzeichenfolge verwendet wird. Ich denke, das ist etwas offensichtlicher, was für meinen Anwendungsfall passiert.

statsApp.directive('activeTab', function ($location) {
  return {
    link: function postLink(scope, element, attrs) {
      scope.$on("$routeChangeSuccess", function (event, current, previous) {
        if (attrs.href!=undefined) { // this directive is called twice for some reason
          // The activeTab attribute should contain a path search string to match on.
          // I.e. <li><a href="#/nested/section1/partial" activeTab="/section1">First Partial</a></li>
          if ($location.path().indexOf(attrs.activeTab) >= 0) {
            element.parent().addClass("active");//parent to get the <li>
          } else {
            element.parent().removeClass("active");
          }
        }
      });
    }
  };
});

HTML sieht jetzt so aus:

<ul class="nav nav-tabs">
  <li><a href="#/news" active-tab="/news">News</a></li>
  <li><a href="#/some/nested/photos/rawr" active-tab="/photos">Photos</a></li>
  <li><a href="#/contact" active-tab="/contact">Contact</a></li>
</ul>
Dave Rapin
quelle
3

Ich fand XMLilleys Antwort die beste und anpassungsfähigste und nicht aufdringlichste.

Ich hatte jedoch eine kleine Panne.

Für die Verwendung mit Bootstrap Nav habe ich Folgendes geändert:

app.directive('activeTab', function ($location) {
    return {
      link: function postLink(scope, element, attrs) {
        scope.$on("$routeChangeSuccess", function (event, current, previous) {
            /*  designed for full re-usability at any path, any level, by using 
                data from attrs
                declare like this: <li class="nav_tab"><a href="#/home" 
                                   active-tab="1">HOME</a></li> 
            */
            if(attrs.href!=undefined){// this directive is called twice for some reason
                // this var grabs the tab-level off the attribute, or defaults to 1
                var pathLevel = attrs.activeTab || 1,
                // this var finds what the path is at the level specified
                    pathToCheck = $location.path().split('/')[pathLevel],
                // this var finds grabs the same level of the href attribute
                    tabLink = attrs.href.split('/')[pathLevel];
                // now compare the two:
                if (pathToCheck === tabLink) {
                  element.parent().addClass("active");//parent to get the <li>
                }
                else {
                  element.parent().removeClass("active");
                }
            }
        });
      }
    };
  });

Ich habe "if (attrs.href! = Undefined)" hinzugefügt, da diese Funktion anscheinend zweimal aufgerufen wird und das zweite Mal einen Fehler erzeugt.

Wie für das HTML:

<ul class="nav nav-tabs">
   <li class="active" active-tab="1"><a href="#/accueil" active-tab="1">Accueil</a></li>
   <li><a active-tab="1" href="#/news">News</a></li>
   <li><a active-tab="1" href="#/photos" >Photos</a></li>
   <li><a active-tab="1" href="#/contact">Contact</a></li>
</ul>
domi
quelle
nvm, es war meine schuld, dass dies zweimal aufgerufen wurde. Ich denke "if (attrs.href! = Undefined)" wird nicht benötigt.
Domi
3

Bootstrap-Beispiel.

Wenn Sie Angulars verwenden, die im Routing (ngview) integriert sind, kann diese Anweisung verwendet werden:

angular.module('myApp').directive('classOnActiveLink', [function() {
    return {
        link: function(scope, element, attrs) {

            var anchorLink = element.children()[0].getAttribute('ng-href') || element.children()[0].getAttribute('href');
            anchorLink = anchorLink.replace(/^#/, '');

            scope.$on("$routeChangeSuccess", function (event, current) {
                if (current.$$route.originalPath == anchorLink) {
                    element.addClass(attrs.classOnActiveLink);
                }
                else {
                    element.removeClass(attrs.classOnActiveLink);
                }
            });

        }
    };
}]);

Angenommen, Ihr Markup sieht folgendermaßen aus:

    <ul class="nav navbar-nav">
        <li class-on-active-link="active"><a href="/orders">Orders</a></li>
        <li class-on-active-link="active"><a href="/distributors">Distributors</a></li>
    </ul>

Ich mag es, dies zu tun, da Sie den gewünschten Klassennamen in Ihrem Attribut festlegen können.

Michael Falck Wedelgård
quelle
2

Sie können den Ort auch einfach in den Bereich einfügen und daraus den Stil für die Navigation ableiten:

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

Dann verwenden Sie es in Ihrem ng-class:

<li ng-class="{active: location.path() == '/search'}">
  <a href="/search">Search><a/>
</li>
Der Hochstapler
quelle
sollte es nicht $ root.location.path () im Markup sein?
Irshu
@Irshu: Das könnte möglicherweise sauberer sein, aber der obige Ansatz hat auch bei mir funktioniert.
Der Hochstapler
2

Eine alternative Möglichkeit ist die Verwendung von ui-sref-active

Eine Direktive, die mit ui-sref zusammenarbeitet, um einem Element Klassen hinzuzufügen, wenn der Status der zugehörigen ui-sref-Direktive aktiv ist, und diese zu entfernen, wenn sie inaktiv ist. Der Hauptanwendungsfall besteht darin, das spezielle Erscheinungsbild von Navigationsmenüs zu vereinfachen, die auf ui-sref basieren, indem die Menüschaltfläche des Status "aktiv" anders angezeigt wird und sich von den inaktiven Menüelementen unterscheidet.

Verwendung:

ui-sref-active = 'class1 class2 class3' - Die Klassen "class1", "class2" und "class3" werden jeweils zum Direktivenelement hinzugefügt, wenn der Status des zugehörigen ui-sref aktiv ist, und entfernt, wenn er inaktiv ist.

Beispiel:
Angesichts der folgenden Vorlage:

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

Wenn der App-Status "app.user" ist und den Statusparameter "user" mit dem Wert "bilbobaggins" enthält, wird der resultierende HTML-Code als angezeigt

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

Der Klassenname wird während der Verknüpfungszeit der Direktiven einmal interpoliert (weitere Änderungen am interpolierten Wert werden ignoriert). Es können mehrere Klassen in einem durch Leerzeichen getrennten Format angegeben werden.

Verwenden Sie die Direktive ui-sref-opts, um Optionen an $ state.go () zu übergeben. Beispiel:

<a ui-sref="home" ui-sref-opts="{reload: true}">Home</a>
George Botros
quelle
Vielen Dank. Es ist sehr nützlich, wenn Sie im ionischen Gerüst arbeiten!
Avijit Gupta
1

Ich stimme Robs Beitrag über ein benutzerdefiniertes Attribut im Controller zu. Anscheinend habe ich nicht genug Repräsentanten, um einen Kommentar abzugeben. Hier ist die angeforderte jsfiddle:

Beispiel HTML

<div ng-controller="MyCtrl">
    <ul>
        <li ng-repeat="link in links" ng-class="{active: $route.current.activeNav == link.type}"> <a href="{{link.uri}}">{{link.name}}</a>

        </li>
    </ul>
</div>

Beispiel app.js.

angular.module('MyApp', []).config(['$routeProvider', function ($routeProvider) {
    $routeProvider.when('/a', {
        activeNav: 'a'
    })
        .when('/a/:id', {
        activeNav: 'a'
    })
        .when('/b', {
        activeNav: 'b'
    })
        .when('/c', {
        activeNav: 'c'
    });
}])
    .controller('MyCtrl', function ($scope, $route) {
    $scope.$route = $route;
    $scope.links = [{
        uri: '#/a',
        name: 'A',
        type: 'a'
    }, {
        uri: '#/b',
        name: 'B',
        type: 'b'
    }, {
        uri: '#/c',
        name: 'C',
        type: 'c'
    }, {
        uri: '#/a/detail',
        name: 'A Detail',
        type: 'a'
    }];
});

http://jsfiddle.net/HrdR6/

Jasontwong
quelle
Ich mag den datengesteuerten Ansatz für die Liste der Links. Einige entscheiden sich möglicherweise dafür, das Array von Links in einen Dienst / eine Fabrik zu verschieben.
Grant Lindsay
1
'use strict';

angular.module('cloudApp')
  .controller('MenuController', function ($scope, $location, CloudAuth) {
    $scope.menu = [
      {
        'title': 'Dashboard',
        'iconClass': 'fa fa-dashboard',
        'link': '/dashboard',
        'active': true
      },
      {
        'title': 'Devices',
        'iconClass': 'fa fa-star',
        'link': '/devices'
      },
      {
        'title': 'Settings',
        'iconClass': 'fa fa-gears',
        'link': '/settings'
      }
    ];
    $location.path('/dashboard');
    $scope.isLoggedIn = CloudAuth.isLoggedIn;
    $scope.isAdmin = CloudAuth.isAdmin;
    $scope.isActive = function(route) {
      return route === $location.path();
    };
  });

Und verwenden Sie das Folgende in der Vorlage:

<li role="presentation" ng-class="{active:isActive(menuItem.link)}" ng-repeat="menuItem in menu"><a href="{{menuItem.link}}"><i class="{{menuItem.iconClass}}"></i>&nbsp;&nbsp;{{menuItem.title}}</a></li>
Yeshodhan Kulkarni
quelle
0

Ich brauchte eine Lösung, die keine Änderungen an den Controllern erfordert, da für einige Seiten nur Vorlagen gerendert werden und es überhaupt keinen Controller gibt. Dank früherer Kommentatoren, die vorgeschlagen haben, habe $routeChangeSuccessich mir so etwas ausgedacht:

# Directive
angular.module('myapp.directives')
.directive 'ActiveTab', ($route) ->
  restrict: 'A'

  link: (scope, element, attrs) ->
    klass = "active"

    if $route.current.activeTab? and attrs.flActiveLink is $route.current.activeTab
      element.addClass(klass)

    scope.$on '$routeChangeSuccess', (event, current) ->
      if current.activeTab? and attrs.flActiveLink is current.activeTab
        element.addClass(klass)
      else
        element.removeClass(klass)

# Routing
$routeProvider
.when "/page",
  templateUrl: "page.html"
  activeTab: "page"
.when "/other_page",
  templateUrl: "other_page.html"
  controller: "OtherPageCtrl"
  activeTab: "other_page"

# View (.jade)
a(ng-href='/page', active-tab='page') Page
a(ng-href='/other_page', active-tab='other_page') Other page

Es hängt nicht von URLs ab und ist daher sehr einfach, es für Unterseiten usw. einzurichten.

szimek
quelle
0

Ich kann mich nicht erinnern, wo ich diese Methode gefunden habe, aber sie ist ziemlich einfach und funktioniert gut.

HTML:

<nav role="navigation">
    <ul>
        <li ui-sref-active="selected" class="inactive"><a ui-sref="tab-01">Tab 01</a></li> 
        <li ui-sref-active="selected" class="inactive"><a ui-sref="tab-02">Tab 02</a></li>
    </ul>
</nav>

CSS:

  .selected {
    background-color: $white;
    color: $light-blue;
    text-decoration: none;
    border-color: $light-grey;
  } 
cfranklin
quelle
0

Wenn Sie ngRoute (für das Routing) verwenden, hat Ihre Anwendung die folgende Konfiguration:

angular
  .module('appApp', [
    'ngRoute'
 ])
config(function ($routeProvider) {
    $routeProvider
      .when('/', {
        templateUrl: 'views/main.html',
        controller: 'MainCtrl',
        controllerAs: 'main'
      })
      .when('/about', {
        templateUrl: 'views/about.html',
        controller: 'AboutCtrl',
        controllerAs: 'about'
      })
}
});

Fügen Sie jetzt einfach einen Controller in dieser Konfiguration hinzu, wie unten beschrieben.

angular
      .module('appApp', [
        'ngRoute'
     ])
    config(function ($routeProvider) {
        $routeProvider
          .when('/', {
            templateUrl: 'views/main.html',
            controller: 'MainCtrl',
            activetab: 'main'
          })
          .when('/about', {
            templateUrl: 'views/about.html',
            controller: 'AboutCtrl',
            activetab: 'about'
          })
    }
    })
  .controller('navController', function ($scope, $route) {
    $scope.$route = $route;
  });

Wie Sie in Ihrer Konfiguration die Registerkarte "Aktiv" erwähnt haben, müssen Sie jetzt nur noch eine aktive Klasse in Ihr <li>oder <a>-Tag einfügen. Mögen,

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

Das heißt, wenn der Benutzer auf eine Info-Seite klickt, wird automatisch die aktuelle Registerkarte identifiziert und die aktive CSS-Klasse angewendet.

Ich hoffe das hilft!

imbond
quelle
-3

Kam hier für die Lösung .. obwohl oben Lösungen funktionieren gut, aber fanden sie ein wenig komplex unnötig. Für Leute, die immer noch nach einer einfachen und ordentlichen Lösung suchen, wird es die Aufgabe perfekt erledigen.

<section ng-init="tab=1">
                <ul class="nav nav-tabs">
                    <li ng-class="{active: tab == 1}"><a ng-click="tab=1" href="#showitem">View Inventory</a></li>
                    <li ng-class="{active: tab == 2}"><a ng-click="tab=2" href="#additem">Add new item</a></li>
                    <li ng-class="{active: tab == 3}"><a ng-click="tab=3" href="#solditem">Sold item</a></li>
                </ul>
            </section>
MGA
quelle