Geçerli menü öğesi nasıl vurgulanır?


205

AngularJS active, geçerli sayfanın bağlantısına bir sınıf ayarlamada herhangi bir şekilde yardımcı oluyor mu ?

Bunun yapılmasının sihirli bir yolu olduğunu hayal ediyorum, ama bulamıyorum.

Menüm şöyle:

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

ve rotalarımda her biri için denetleyicilerim var: TasksControllerve ActionsController.

Ama "aktif" sınıfı akontrolörlere bağlamanın bir yolunu bulamıyorum .

İpucu var mı?

Yanıtlar:


265

görüşte

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

kontrolörde

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

Bununla görevler bağlantısı, '/ görevler' ile başlayan herhangi bir url'de etkin sınıfa sahip olacaktır (örneğin '/ görevler / 1 / raporlar')


4
Bu hem "/" hem de "/ herhangi bir şey" ile eşleşir veya "/ test", "/ test / this", "/ test / this / path" gibi benzer URL'lere sahip birden fazla menü öğeniz varsa, / test, tüm bu seçenekleri vurgulayacaktır.
Ben Lesh

3
Bunu ($ location.path () == path) olarak değiştirdim ve y yolu "/ blah" vb
Tim

113
Ben gösterimini tercih ngClass="{active: isActive('/tasks')}, isActive()o kontrolörü ve işaretleme / stil decouples olarak bir boolean dönecekti.
Ed Hinchliffe

6
Herhangi birinin yolun "/" olması durumunda kodun ikiye katlanmamasını merak etmesi durumunda, budur (biçimlendirme için üzgünüm): $ scope.getClass = function (path) {if ($ location.path (). substr (0, path.length) == path) {if (path == "/" && $ location.path () == "/") {return "active"; } else if (yol == "/") {return ""; } "aktif"}

1
EdHinchliffe, bunun işaretleme ve mantığı karıştırdığına dikkat çekti. Ayrıca yolun kopyalanmasına yol açar ve bu nedenle kopyalama ve yapıştırma hatalarına eğilimli olabilir. @Kfis'in direktif yaklaşımının daha fazla satır olmasına rağmen daha fazla kullanılabilir olduğunu ve biçimlendirmeyi daha temiz tuttuğunu gördüm.
A. Murray

86

Bir link üzerinde direktif kullanmanızı öneririm.

Ama henüz mükemmel değil. Hashbanglara dikkat edin;)

İşte direktif için javascript:

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

ve html'de nasıl kullanılacağı aşağıda açıklanmıştır:

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

daha sonra css ile şekillendirme:

.active { color: red; }

Ne demek istediğini emin değilim "hashbangs dikkat". Her zaman işe yarayacak gibi görünüyor. Karşı bir örnek verebilir misiniz?
Andriy Drozdyuk

7
Bootstrap'ı kullanmaya çalışıyorsanız ve bir li içindeki a a'nın href'inin karmasına dayalı olarak ayarlamanız gerekiyorsa, kullanın var path = $(element).children("a")[0].hash.substring(1);. Bu gibi bir stil için işe yarayacak<li active-link="active"><a href="#/dashboard">Dashboard</a></li>
Dave

2
Ben değiştirecek scope.$watch('location.path()', function(newPath) {için scope.$on('$locationChangeStart', function(){.
sanfilippopablo

2
Ng-href kullanıyorsanız sadece şunu değiştirin: var path = attrs.href; - var path = attrs.href||attrs.ngHref;
William Neely

Bootstrap kullanıyorsanız ve aktif sınıfı üzerine koymanız gerekiyorsa<li>element.addClass(clazz);element.parent().addClass(clazz);
JamesRLamar

47

İşte Angular ile iyi çalışan basit bir yaklaşım.

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

AngularJS denetleyicinizde:

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

Bu konuda benzer başka cevaplar da var.

Angular JS ile bootstrap navbar aktif sınıf nasıl ayarlanır?


1
Değişkeni gereksiz olduğu için kaldırın. Sadece karşılaştırma sonucunu döndürün. return viewLocation === $location.path()
afarazit

33

Tartışmaya iki sentimi eklemek için saf bir açısal modül yaptım (jQuery yok) ve ayrıca veri içeren karma URL'lerle de çalışacak. (ör. #/this/is/path?this=is&some=data)

Modülü sadece bağımlılık olarak ve auto-activemenünün atalarından birine eklersiniz . Bunun gibi:

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

Ve modül şöyle görünür:

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

(Tabii ki sadece direktif bölümünü kullanabilirsiniz)

Bunun , en azından veya adil olması gereken boş karmalar (örneğin example.com/#veya sadece example.com) için işe yaramadığını da fark etmek gerekir . Ancak bu ngResource ve benzerlerinde otomatik olarak gerçekleşir.example.com/#/example.com#/

Ve işte keman: http://jsfiddle.net/gy2an/8/


1
Harika bir çözüm, ancak ilk sayfa yüklemesinde işe yaramadı, sadece uygulama canlıyken locationChange üzerinde. Snippet'inizi bununla başa çıkacak şekilde güncelledim .
Jerry

@Jarek: Teşekkürler! Değişikliklerinizi uyguladınız. Kişisel olarak bununla ilgili herhangi bir sorun yaşamadım, ancak çözümünüz bu sorunla karşılaşacak olanlar için iyi ve istikrarlı bir çözüm gibi görünüyor.
Pylinux

2
Şimdi başkalarının iyi fikirleri varsa çekme istekleri için bir Github repo oluşturdum: github.com/Karl-Gustav/autoActive
Pylinux

Ben sadece ng-href kullanıyorsanız oluşacak birkaç hata düzeltildi .. Bu burada bulunur: github.com/Karl-Gustav/autoActive/pull/3
Blake Niemyjski

Bu komut dosyasının bir yol belirtmenize izin vermesi iyi olur, böylece diğer öğeleri etkinleştirmesini sağlayabilirsiniz.
Blake Niemyjski

22

Benim durumumda, navigasyondan sorumlu basit bir denetleyici oluşturarak bu sorunu çözdüm

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

Ve öğeye sadece ng sınıfı ekleyerek:

<ul class="nav" ng-controller="NavigationCtrl">
  <li ng-class="{ active: isCurrentPath('/') }"><a href="#/">Home</a></li>
  <li ng-class="{ active: isCurrentPath('/about') }"><a href="#/about">About</a></li>
  <li ng-class="{ active: isCurrentPath('/contact') }"><a href="#/contact">Contact</a></li>
</ul>

14

İçin AngularUI Yönlendirici kullanıcıları:

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

Ve bu activeseçilen nesneye bir sınıf yerleştirir.


2
Bu bir ui-yönlendirici yönergesidir ve yerleşik yönlendirici, diğer bir deyişle ngRoute kullanırsanız çalışmaz. Bununla birlikte, ui-yönlendirici harika.
moljac024

Katılıyorum, aslında bir ui-router tek çözüm olduğunu belirtmeyi unuttum.
frankie4fingers

13

ng-classDeğişken ve css sınıfını bağlayan bir yönerge vardır . Nesneyi de kabul eder (className ve bool değeri çiftleri).

İşte örnek: http://plnkr.co/edit/SWZAqj


Teşekkürler, ancak bu aşağıdaki gibi yollarla çalışmaz: /test1/blahblahya da öyle mi?
Andriy Drozdyuk

Yani active: activePath=='/test1'otomatik olarak bir "aktif" döndüren yolun verilen dize ile başladığını mı söylüyorsunuz ? Bu bir tür önceden tanımlanmış operatör veya normal ifade mi?
Andriy Drozdyuk

Üzgünüm, ihtiyacınızı doğru anladığımı sanmıyorum. İşte benim yeni tahminim, hem 'test1' bağlantısını hem de 'test1 / blahblah' bağlantısını vurgulamak istiyorsanız, 'test1 / blahblah' rotası vurgulanır. "Haklı mıyım? çalışırlar.
Tosh

3
İşte güncellenmiş plnkr: plnkr.co/edit/JI5DtK (tahmin edilen gereksinimi karşılayan) sadece alternatif bir çözüm göstermek için.
Tosh

Orada ne yaptığınızı görüyorum. Ama html'de tekrarlanan ==kontrollerin hayranı değilim .
Andriy Drozdyuk

13

Cevap Renan-Tomal-fernandes @ dan iyidir, ama doğru işe birkaç iyileştirmeyi gerekli. Olduğu gibi, başka bir bölümde olsanız bile, giriş sayfasının (/) bağlantısını her zaman tetiklenmiş olarak algılar.

Bu yüzden biraz geliştirdim, işte kod. Aktif parçası yerine öğe içinde Bootstrap ile çalışır .<li><a>

kontrolör

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

şablon

<div class="nav-collapse collapse">
  <ul class="nav">
    <li ng-class="getClass('/')"><a href="#/">Home</a></li>
    <li ng-class="getClass('/contents/')"><a href="#/contests/">Contents</a></li>
    <li ng-class="getClass('/data/')"><a href="#/data/">Your data</a></li>
  </ul>
</div>

10

Yukarıdaki mükemmel önerileri okuduktan sonra bulduğum çözüm. Benim özel durumumda, Bootstrap sekmeleri bileşenini menüm olarak kullanmaya çalışıyordum , ancak bunun Açısal UI sürümünü kullanmak istemedim çünkü sekmelerin her sekmenin yer imi yapılabildiği bir menü gibi davranmasını istiyorum, tek bir sayfa için gezinme işlevi gören sekmeler yerine. ( Bootstrap sekmelerinin Angular-UI sürümünün nasıl görüneceğiyle ilgileniyorsanız, http://angular-ui.github.io/bootstrap/#/tabs adresine bakın ).

Kfis'in bununla başa çıkmak için kendi direktifinizi oluşturma konusundaki cevabını gerçekten çok sevdim, ancak her bir bağlantıya yerleştirilmesi gereken bir direktifin olması hantal görünüyordu. Bu yüzden onun yerine bir kez yerleştirilmiş kendi Açısal yönergemi oluşturdum ul. Başka birinin de aynı şeyi yapmaya çalışması durumunda, burada söylediğimi düşündüm, ancak dediğim gibi, yukarıdaki çözümlerin çoğu da işe yarıyor. Bu, javascript giderken biraz daha karmaşık bir çözümdür, ancak minimum işaretleme ile yeniden kullanılabilir bir bileşen oluşturur.

İşte direktif için javascript ve aşağıdakiler için rota sağlayıcı ng:view:

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

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

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

    };

 }]);

Sonra html'nizde basitçe:

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

İşte bunun için dalgıç: http://plnkr.co/edit/xwGtGqrT7kWoCKnGDHYN?p=preview .


9

Bunu çok basit bir şekilde uygulayabilirsiniz, işte bir örnek:

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

</div>

Ve Denetleyiciniz şu olmalıdır:

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


4

Denetleyici kapsamı dışında bulunan menü ile benzer bir sorun vardı . Bunun en iyi çözüm veya önerilen bir çözüm olup olmadığından emin değilim ama bu benim için işe yaradı. Uygulama yapılandırmamıza aşağıdakileri ekledim:

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

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

Sonra görünümünde var:

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

Um ... kabul edilen cevaptan daha karmaşık görünüyor. Bunun avantajını bundan açıklayabilir misiniz?
Andriy Drozdyuk

1
Menünüz ng-view dışındayken senaryoda buna ihtiyacınız olacaktır. Görünüm denetleyicisi iletişim dışında etkinleştirmek için $ rootScope kullandığım dışında herhangi bir şeye erişimi olmayacak. Menünüz ng görünümündeyse, bu çözümü kullanmanızın bir yararı yoktur.
mrt

4

Bootstrap 4.1 ile Açısal Sürüm 6'yı kullanma

Aşağıda görüldüğü gibi halledebildim.

Aşağıdaki örnekte, URL '/ contact' ifadesini gördüğünde, önyükleme etkin aktif html etiketine eklenir. URL değiştiğinde kaldırılır.

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

Bu yönerge, bağlantının yolu etkin olduğunda bir öğeye bir CSS sınıfı eklemenizi sağlar.

Açısal web sitesinde daha fazla bilgi edinin


3

Bir yönerge kullanmak (burada DOM manipülasyonu yaptığımız için) aşağıdakiler muhtemelen "açısal yol" a en yakın şeydir:

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

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

        var menuContext = attrs.filter;

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

        }

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

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

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

Ardından HTML'niz şöyle görünür:

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

İlginç. Ancak menu-itemher satırda gereksiz görünüyor. Belki bir özniteliğe ul(ör. <ul menu>) Bir özellik eklemek daha iyi olurdu, ancak bunun mümkün olup olmadığından emin değilim.
Andriy Drozdyuk

Daha yeni bir sürümle güncellendi - statik sıralanmamış bir liste yerine, şimdi Boostrap açılır menüsünü bir seçim listesi olarak kullanıyorum.
Wesley Hales

Bu en çok deyimsel açısal gibi görünüyor. Stackoverflow.com/questions/14994391/… adresindeki tavsiyeye uyuyor gibi görünüyor ve görünümde, href ve ng sınıfında yolun kopyalanmasını önlüyor.
fundead

2

Ben böyle yaptım:

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

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

Bu, track-active yönergesine sahip bir bölümde bağlantılara sahip olmanızı sağlar:

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

Bu yaklaşım benim için diğerlerinden çok daha temiz görünüyor.

Ayrıca, jQuery kullanıyorsanız, jQlite sadece temel seçici desteğine sahip olduğundan çok daha temiz yapabilirsiniz. Açısal içermeden önce jquery içeren çok daha temiz bir sürüm şöyle görünecektir:

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

İşte bir jsFiddle


2

Bu soruna çözümüm route.current, açısal şablonda kullanın .

Menünüzde /tasksvurgulanacak rotanız olduğundan menuItem, modülünüz tarafından bildirilen rotalara kendi mülkünüzü ekleyebilirsiniz :

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

Ardından şablonunuzda tasks.htmlaşağıdaki ng-classyönergeleri kullanabilirsiniz :

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

Bence bu, önerilen tüm çözümlerden çok daha temiz.


1

Burada kfis yönergesinde farklı düzeylerde yol eşleşmesine izin vermek için yaptığım bir uzantı var. Aslında, tam eşleme yuvalama ve varsayılan durum yönlendirmelerine izin vermediğinden, URL yollarını belirli bir derinliğe kadar eşleme ihtiyacını buldum. Bu yardımcı olur umarım.

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

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

        };
    }]);

Ve bağlantıyı nasıl kullanacağım

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

Bu yönerge, yönerge için öznitelik değerinde belirtilen derinlik düzeyiyle eşleşecektir. Sadece başka yerlerde birçok kez kullanılabileceği anlamına gelir.


1

İşte aktif bağlantıları vurgulamak için başka bir direktif.

Ana Özellikler:

  • Dinamik açısal ifadeler içeren href ile iyi çalışır
  • Hash-bang navigasyon ile uyumlu
  • Aktif sınıfın bağlantının kendisine değil, ana sınıfın uygulanması gereken Bootstrap ile uyumlu
  • Herhangi bir iç içe yol etkinse bağlantıyı etkinleştirmeye izin verir
  • Etkin değilse bağlantının devre dışı bırakılmasına izin verir

Kod:

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

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

                return current;
            }

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

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

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

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

Kullanımı:

Açısal ifadeli basit bir örnek, $ scope.var = 2 diyelim , ardından konum / url / 2 ise bağlantı etkin olacaktır :

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

Bootstrap örneği, üst li aktif sınıf alacak:

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

İç içe URL'lerle ilgili örnek, herhangi bir iç içe URL etkinse bağlantı etkin olacaktır (yani / url / 1 , / url / 2 , url / 1/2 / ... )

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

Karmaşık örnekte bağlantı bir url'yi ( / url1 ) gösterir, ancak başka bir URL seçilirse etkin olur ( / url2 ):

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

Devre dışı bırakılmış örnek, etkin değilse 'devre dışı' sınıfına sahip olacaktır :

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

Tüm active-link- * özellikleri herhangi bir kombinasyonda kullanılabilir, bu nedenle çok karmaşık koşullar uygulanabilir.


1

Yönerge için bağlantıların her bir bağlantıyı seçmek yerine bir sarıcıda olmasını istiyorsanız (Batarang'ın kapsamına bakmayı kolaylaştırır), bu da oldukça iyi çalışır:

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

          scope.location = $location;

          classSelected = 'selected';

          navLinks = element.find('a');

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

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

İşaretleme sadece şöyle olur:

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

Bu örnekte 'tam yağlı' jQuery kullandığımı da belirtmeliyim, ancak filtreleme vb. İle yaptığımı kolayca değiştirebilirsiniz.


1

İşte iki sentim, bu iyi çalışıyor.

NOT: Bu çocuk sayfalarıyla eşleşmiyor (bu ihtiyacım olan şey).

Görünüm:

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

Denetleyici:

// make sure you inject $location as a dependency

$scope.isCurrentLocation = function(path){
    return path === $location.path()
}

1

@Kfis'in cevabına göre, yorumlar ve önerim, aşağıdaki gibi son direktif:

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

ve html'de nasıl kullanılacağı aşağıda açıklanmıştır:

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

daha sonra css ile şekillendirme:

.active { color: red; }

1

UI-yönlendirici kullananlar için cevabım Ender2050'lere biraz benziyor, ancak bunu eyalet adı testi ile yapmayı tercih ediyorum:

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

karşılık gelen HTML:

<ul class="nav nav-sidebar">
    <li ng-class="{ active: isActive('app.home') }"><a ui-sref="app.home">Dashboard</a></li>
    <li ng-class="{ active: isActive('app.tiles') }"><a ui-sref="app.tiles">Tiles</a></li>
</ul>

1

Yukarıdaki direktif önerilerinin hiçbiri benim için yararlı olmadı. Böyle bir bootstrap navbar'ınız varsa

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

(Bu bir olabilir $ yo angularardından eklemek istediğiniz başlangıç) .activeiçin ana <li> eleman sınıf listesinde değil, eleman kendisi; yani <li class="active">..</li>. Bu yüzden şunu yazdım:

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

kullanım set-parent-active; .activevarsayılan olduğundan ayarlanması gerekmez

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

ve üst <li>öğe .activebağlantı etkin olduğunda olacaktır . Alternatif kullanmak için .activebenzeri sınıf .highlightbasitçe,

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

Kapsam denedim. ("$ RouteChangeSuccess", işlev (olay, geçerli, önceki) {cameraActiveClass ();}); ancak yalnızca bağlantı tıklandığında çalışır, 'sayfa yüklenirken' (yenile düğmesine tıklayarak) çalışmaz. konumu izlemek benim için çalıştı
sawe

0

Benim için en önemlisi tüm bootstrap varsayılan kodunu değiştirmek değildi. Burada menü seçeneklerini arayan ve sonra istediğimiz davranışı ekleyen menü denetleyicim.

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

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

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

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

0

aynı sorunu vardı. İşte benim çözümüm :

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

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

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

            if state isnt -1 or substate isnt -1
              element.addClass 'selected'
              element.parent().addClass 'current-menu-item'
            else if href is '#' and loc is '#/'
              element.addClass 'selected'
              element.parent().addClass 'current-menu-item'
            else
              element.removeClass 'selected'
              element.parent().removeClass 'current-menu-item'
  ])

0

Bunun için bir direktif yazdım.

Kullanımı:

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

Uygulama:

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

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

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

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

Testler:

'use strict';

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

0

Rota:

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

Html menüsü:

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

Kontrol eden, denetleyici:

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

Burada bulduğum sorun, menü öğesinin yalnızca tam sayfa yüklendiğinde etkin olmasıdır. Kısmi görünüm yüklendiğinde menü değişmez. Biri neden olduğunu biliyor mu?


0
$scope.getClass = function (path) {
return String(($location.absUrl().split('?')[0]).indexOf(path)) > -1 ? 'active' : ''
}


<li class="listing-head" ng-class="getClass('/v/bookings')"><a href="/v/bookings">MY BOOKING</a></li>
<li class="listing-head" ng-class="getClass('/v/fleets')"><a href="/v/fleets">MY FLEET</a></li>
<li class="listing-head" ng-class="getClass('/v/adddriver')"><a href="/v/adddriver">ADD DRIVER</a></li>
<li class="listing-head" ng-class="getClass('/v/bookings')"><a href="/v/invoice">INVOICE</a></li>
<li class="listing-head" ng-class="getClass('/v/profile')"><a href="/v/profile">MY PROFILE</a></li>
<li class="listing-head"><a href="/v/logout">LOG OUT</a></li>

0

En kolay çözümü buldum. HTML'deki indexOf'u karşılaştırmak için

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

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



<li class="{{isCurrentPath.indexOf('help')>-1 ? 'active' : '' }}">
<a href="/#/help/">
          Help
        </a>
</li>
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.