वर्तमान मेनू आइटम को कैसे हाइलाइट करें?


205

क्या AngularJS activeवर्तमान पृष्ठ के लिए लिंक पर एक कक्षा स्थापित करने में किसी भी तरह से मदद करता है ?

मुझे लगता है कि यह कुछ जादुई तरीका है, लेकिन यह मुझे नहीं मिल रहा है।

मेरा मेनू ऐसा दिखता है:

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

और मेरे पास मेरे मार्गों में से प्रत्येक के लिए नियंत्रक हैं: TasksControllerऔर ActionsController

लेकिन मैं aनियंत्रकों के लिंक पर "सक्रिय" वर्ग को बांधने का एक तरीका नहीं खोज सकता ।

कोई संकेत?

जवाबों:


265

देखने पर

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

नियंत्रक पर

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

इसके साथ टास्क लिंक में '/ कार्य' (जैसे '/ कार्य / 1 / रिपोर्ट) के साथ शुरू होने वाले किसी भी यूआरएल में सक्रिय वर्ग होगा।


4
यह "/" और "/ कुछ भी" दोनों का मिलान करता है या यदि आपके पास समान मेनू वाले एकाधिक मेनू आइटम हैं, जैसे "/ परीक्षण", "/ परीक्षण / यह", "/ परीक्षण / इस / पथ" यदि आप चालू थे / परीक्षण, यह उन सभी विकल्पों को उजागर करेगा।
बेन लेश

3
मैंने इसे बदल दिया है अगर ($ स्थान.पाथ () == पथ) और, y पथ "/ ब्ला" है आदि
टिम

113
मैं नोटेशन पसंद करता हूं ngClass="{active: isActive('/tasks')}, जहां isActive()एक बूलियन लौटाएगा क्योंकि यह नियंत्रक और मार्कअप / स्टाइल को डिकॉउन्ड करता है।
एड हिंचलिफ़

6
बस अगर कोई व्यक्ति कोड के बारे में सोच रहा था कि क्या पथ "/" है, तो यह दोगुना है (यह प्रारूपण के लिए खेद है): $ गुंजाइश.getClass = फ़ंक्शन (पथ) {if ($ location.path) ()। root (0, path.length) == पाथ) {if (पाथ == "/" & "$ लोकेशन ।पथ () ==" / ") {वापसी" सक्रिय "; } और अगर (पथ == "/") {वापसी ""; } वापसी "सक्रिय"} बाकी {वापसी ""}}

1
EdHinchliffe ने पहले ही बताया कि यह मार्कअप और लॉजिक को मिलाता है। यह मार्ग को डुप्लिकेट करने की ओर भी ले जाता है और त्रुटियों को कॉपी और पेस्ट करने के लिए प्रवण हो सकता है। मैंने पाया है कि @kfis द्वारा निर्देश दृष्टिकोण, हालांकि अधिक लाइनें, अधिक पुन: प्रयोज्य है और मार्कअप क्लीनर रखता है।
ए। मुरे

86

मैं एक लिंक पर एक निर्देश का उपयोग करने का सुझाव देता हूं।

लेकिन अभी तक यह सही नहीं है। हैशबैंग के लिए बाहर देखो;)

यहाँ निर्देशन के लिए जावास्क्रिप्ट है:

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

और यहाँ इसका उपयोग 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>

सीएसएस के साथ बाद में स्टाइल:

.active { color: red; }

मुझे यकीन नहीं है कि आप "हैशबैंग के लिए बाहर देखो" से क्या मतलब है। ऐसा लगता है कि यह हमेशा काम करेगा। क्या आप एक प्रति-उदाहरण प्रदान कर सकते हैं?
एंड्री Drozdyuk

7
यदि आप बूटस्ट्रैप का उपयोग करने की कोशिश कर रहे हैं और एक ली के भीतर एक href के हैश के आधार पर सेट करने की आवश्यकता है, तो उपयोग करें var path = $(element).children("a")[0].hash.substring(1);। यह एक शैली के लिए काम करेगा जैसे<li active-link="active"><a href="#/dashboard">Dashboard</a></li>
डेव

2
मैं बदल जाएगा scope.$watch('location.path()', function(newPath) {के लिए scope.$on('$locationChangeStart', function(){
sanfilippopablo

2
यदि आप एनजी-एचआरईआर का उपयोग कर रहे हैं तो बस बदलें: var path = attrs.href; से var path = attrs.href||attrs.ngHref;
विलियम नीली

आप पर सक्रिय वर्ग डाल करने के लिए बूटस्ट्रैप और जरूरत का उपयोग करते हैं <li>, आप बदल सकते हैं element.addClass(clazz);करने के लिएelement.parent().addClass(clazz);
JamesRLamar

47

यहां एक सरल दृष्टिकोण है जो एंगुलर के साथ अच्छी तरह से काम करता है।

<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 नियंत्रक के भीतर:

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

इस धागे में कई अन्य समान उत्तर हैं।

कोणीय जेएस के साथ बूटस्ट्रैप नवबार सक्रिय वर्ग कैसे सेट करें?


1
चर को हटा दें क्योंकि यह अनावश्यक है। बस तुलना परिणाम वापस करें। return viewLocation === $location.path()
अफराजित

33

बस बहस में अपने दो सेंट जोड़ने के लिए मैंने एक शुद्ध कोणीय मॉड्यूल (कोई jQuery) नहीं बनाया है, और यह डेटा वाले हैश उरल्स के साथ भी काम करेगा। (उदा #/this/is/path?this=is&some=data)

आप बस मॉड्यूल को एक निर्भरता के रूप में और auto-activeमेनू के पूर्वजों में से एक में जोड़ते हैं । ऐशे ही:

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

और मॉड्यूल इस तरह दिखता है:

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

(आप निश्चित रूप से सिर्फ निर्देश भाग का उपयोग कर सकते हैं)

यह भी ध्यान देने योग्य है कि यह खाली हैश के लिए काम नहीं करता है (जैसे example.com/#या सिर्फ example.com) इसे कम से कम example.com/#/या बस करने की आवश्यकता है example.com#/। लेकिन यह स्वचालित रूप से ngResource और पसंद के साथ होता है।

और यहाँ फिडेल है: http://jsfiddle.net/gy2an/8/


1
महान समाधान, हालांकि यह शुरुआती पेज लोड पर काम नहीं करता था, जबकि ऐप लाइव होने पर सिर्फ लोकेशनचेंज पर। मैंने आपके स्निपेट को अपडेट कर दिया है।
जेरी

@ जर्क: धन्यवाद! अपने बदलावों को लागू किया है। मुझे व्यक्तिगत रूप से इससे कोई समस्या नहीं है, लेकिन आपका समाधान उन लोगों के लिए एक अच्छा स्थिर समाधान है, जिन्हें इस समस्या में भाग लेना चाहिए।
पाइलिनक्स

2
मैंने अब पुल अनुरोधों के लिए एक Github repo बनाया है अगर किसी और के पास कोई अच्छा विचार है: github.com/Karl-Gustav/autoActive
Pylinux

मैंने अभी कुछ और कीड़े तय किए हैं जो अगर आप ng-href का उपयोग कर रहे थे .. तो यह यहाँ पाया गया है: github.com/Karl-Gustav/autoActive/pull/3
ब्लेक नीमेज्स्की

यह अच्छा होगा यदि यह स्क्रिप्ट आपको एक पथ निर्दिष्ट करने की अनुमति देता है ताकि आप इसे अन्य तत्वों को सक्रिय कर सकें।
ब्लेक नीमेज्स्की

22

मेरे मामले में मैंने नेविगेशन के लिए जिम्मेदार एक साधारण नियंत्रक बनाकर इस समस्या को हल किया

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

और जैसे तत्व में सिर्फ एनजी-क्लास जोड़कर:

<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

के लिए AngularUI रूटर उपयोगकर्ताओं:

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

और जो activeचयनित है उस ऑब्जेक्ट पर एक क्लास लगाएगा।


2
यह एक यूआई-राउटर निर्देश है और यदि आप बिल्ट-इन राउटर, उर्फ ​​एनकाउंटर का उपयोग करते हैं तो यह काम नहीं करता है। उस ने कहा, ui- राउटर कमाल है।
moljac024

सहमत हूं, मैं मूल रूप से उल्लेख करना भूल गया कि यह एक यूआई-राउटर केवल समाधान था।
frankie4fingers

13

एक ng-classनिर्देश है, जो चर और सीएसएस वर्ग को बांधता है। यह ऑब्जेक्ट (क्लासनेम बनाम बूल वैल्यू पेयर) को भी स्वीकार करता है।

यहाँ उदाहरण है, http://plnkr.co/edit/SWZAqj


धन्यवाद, लेकिन यह पथ के साथ काम नहीं करेगा जैसे: /test1/blahblahया यह होगा?
एंड्री Drozdyuk

तो क्या आप कह रहे हैं कि active: activePath=='/test1'स्वचालित रूप से एक "सक्रिय" रिटर्न देता है पथ दिए गए स्ट्रिंग से शुरू होता है? क्या यह किसी प्रकार का पूर्वनिर्धारित ऑपरेटर या रेगेक्स है?
एंड्री Drozdyuk

क्षमा करें, मुझे नहीं लगता कि मैंने आपकी आवश्यकता को सही ढंग से समझा। यहाँ मेरा नया अनुमान है, आप दोनों 'टेस्ट 1' लिंक और 'टेस्ट 1 / ब्लाब्लह' लिंक को हाइलाइट करना चाहते हैं जब रूट 'टेस्ट 1 / ब्लाब्लह' हो। "क्या मैं सही हूं? यदि यह आवश्यकता है, तो आप सही हैं कि इसका समाधान नहीं है" काम।
तोश

3
यहाँ अद्यतन किया गया है plnkr: plnkr.co/edit/JI5DtK (जो अनुमानित आवश्यकता को पूरा करता है) बस एक वैकल्पिक समाधान दिखाने के लिए।
तोश

आपने वहां क्या किया वह मैने देखा। लेकिन मैं ==html में बार-बार आने वाले चेक का प्रशंसक नहीं हूं ।
एंड्री Drozdyuk

13

इस सवाल का जवाब @ Renan-Tomal-फर्नांडीस से अच्छा है, लेकिन सही ढंग से काम करने के लिए कुछ सुधार की जरूरत है। जैसा कि था, यह हमेशा होम पेज (/) के ट्रिगर के रूप में लिंक का पता लगाएगा, भले ही आप दूसरे सेक्शन में हों।

इसलिए मैंने इसे थोड़ा सुधार दिया, यहां कोड है। मैं बूटस्ट्रैप के साथ काम करता हूं इसलिए सक्रिय भाग के <li>बजाय तत्व में है <a>

नियंत्रक

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

खाका

<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

यहाँ समाधान है कि मैं ऊपर कुछ उत्कृष्ट सुझावों को पढ़ने के बाद आया हूँ। मेरी विशेष स्थिति में, मैं अपने मेनू के रूप में बूटस्ट्रैप टैब घटक का उपयोग करने की कोशिश कर रहा था , लेकिन इस के कोणीय-यूआई संस्करण का उपयोग नहीं करना चाहता था क्योंकि मैं चाहता हूं कि टैब एक मेनू के रूप में कार्य करें, जहां प्रत्येक टैब बुकमार्क-सक्षम हो, एक पृष्ठ के लिए नेविगेशन के रूप में कार्य करने वाले टैब के बजाय। ( Http://angular-ui.github.io/bootstrap/#/tabs देखें यदि आप रुचि रखते हैं कि बूटस्ट्रैप टैब का कोणीय-यूआई संस्करण कैसा दिखता है)।

मुझे वास्तव में इसे संभालने के लिए अपना स्वयं का निर्देश बनाने के बारे में kfis का उत्तर पसंद आया, हालांकि यह एक ऐसा निर्देश था जो हर एक लिंक पर रखा जाना आवश्यक था। इसलिए मैंने अपना खुद का कोणीय निर्देश बनाया है जो एक बार के बजाय रखा गया हैul । बस अगर कोई और एक ही काम करने की कोशिश कर रहा है, तो मैंने सोचा कि मैं इसे यहां पोस्ट करूंगा, हालांकि जैसा कि मैंने कहा, उपरोक्त समाधानों में से कई काम करते हैं। यह एक और अधिक जटिल समाधान है जहाँ तक जावास्क्रिप्ट जाता है, लेकिन यह न्यूनतम मार्कअप के साथ एक पुन: प्रयोज्य घटक बनाता है।

यहाँ निर्देशन के लिए जावास्क्रिप्ट और इसके लिए मार्ग प्रदाता है 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");
            });
        }

    };

 }]);

तो अपने HTML में आप बस:

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

यहाँ इसके लिए प्लंकर है: http://plnkr.co/edit/xwGtGqrT7kWoCKnGDHYN?p=preview


9

आप इसे बहुत सरलता से लागू कर सकते हैं, यहाँ एक उदाहरण है:

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

और आपका नियंत्रक यह होना चाहिए:

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

5

कोणीय-यूआई-राउटर के यूआई-एसएफआर-सक्रिय निर्देश https://github.com/angular-ui/ui-router/wiki/Quick-Reference#statename का उपयोग करें

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


4

कंट्रोलर स्कोप के बाहर स्थित मेनू के साथ भी मुझे ऐसी ही समस्या थी । यकीन नहीं होता कि यह सबसे अच्छा समाधान है या एक अनुशंसित है लेकिन यह वही है जो मेरे लिए काम करता है। मैंने अपने एप्लिकेशन कॉन्फ़िगरेशन में निम्न शामिल किया है:

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

फिर मेरे विचार में:

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

उम ... यह अधिक जटिल लगता है कि स्वीकृत उत्तर। क्या आप उस एक पर इस लाभ का वर्णन कर सकते हैं?
एंड्री Drozdyuk

1
आपको इस परिदृश्य में इसकी आवश्यकता होगी जब आपका मेनू एनजी-व्यू के बाहर होगा। कंट्रोलर अभ्यस्त के पास ऐसी किसी भी चीज़ की पहुँच नहीं है जो मैंने संचार को सक्षम करने के लिए $ rootScope का उपयोग किया है। यदि आपका मेनू एनजी-व्यू के अंदर है, तो इस समाधान का उपयोग करने से आपको कोई लाभ नहीं है।
मर्ट

4

बूटस्ट्रैप 4.1 के साथ कोणीय संस्करण 6 का उपयोग करना

मैं इसे प्राप्त करने में सक्षम था जैसा कि नीचे देखा गया है।

नीचे दिए गए उदाहरण में, जब URL '/ संपर्क' देखता है, तो बूटस्ट्रैप सक्रिय तब html टैग में जोड़ा जाता है। जब URL बदलता है तब इसे हटा दिया जाता है।

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

यह निर्देश लिंक के मार्ग के सक्रिय होने पर आपको एक तत्व में CSS वर्ग जोड़ने की सुविधा देता है।

आगे पढ़ें कोणीय वेबसाइट


3

एक निर्देश का उपयोग करना (जब से हम यहां डोम हेरफेर कर रहे हैं) निम्नलिखित चीजें "कोणीय तरीका" करने के लिए संभवतः सबसे निकटतम है:

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

तब आपका HTML ऐसा दिखेगा:

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

दिलचस्प। लेकिन menu-itemप्रत्येक पंक्ति पर बेमानी लगता है। शायद ulएलीमेंट टू एलीमेंट (जैसे <ul menu>) बेहतर होगा, लेकिन मुझे यकीन नहीं है कि यह संभव होगा।
एंड्री Drozdyuk

बस एक नए संस्करण के साथ अपडेट किया गया - एक स्थिर अनियंत्रित सूची के बजाय, अब मैं चयन सूची के रूप में Boostrap ड्रॉपडाउन-मेनू का उपयोग कर रहा हूं।
वेस्ले हेल्स

यह मुहावरेदार कोणीय की तरह सबसे अधिक लगता है। यह stackoverflow.com/questions/14994391/… पर दी गई सलाह के साथ फिट बैठता है , और यह दृश्य में पथ को हाइपर और एनजी-क्लास में डुप्लिकेट करने से बचता है।
निधि

2

मैंने इसे इस तरह किया:

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

यह आपको उस सेक्शन में लिंक करने में सक्षम बनाता है जिसमें ट्रैक-एक्टिव डायरेक्टिव है:

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

यह दृष्टिकोण मुझे दूसरों की तुलना में बहुत साफ लगता है।

इसके अलावा, यदि आप jQuery का उपयोग कर रहे हैं, तो आप इसे बहुत अच्छा बना सकते हैं क्योंकि jQlite में केवल मूल चयनकर्ता का समर्थन है। कोणीय से पहले शामिल jquery के साथ एक बहुत क्लीनर संस्करण इस तरह दिखेगा:

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

यहाँ एक jsFiddle है


2

इस समस्या का मेरा समाधान, route.currentकोणीय टेम्पलेट में उपयोग करें ।

जैसा कि आपके पास /tasksअपने मेनू में हाइलाइट करने के लिए मार्ग है, आप menuItemअपने मॉड्यूल द्वारा घोषित मार्गों में अपनी संपत्ति जोड़ सकते हैं :

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

फिर अपने टेम्पलेट में tasks.htmlआप निम्नलिखित ng-classनिर्देशों का उपयोग कर सकते हैं :

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

मेरी राय में, यह सभी प्रस्तावित समाधानों की तुलना में बहुत साफ है।


1

यहाँ kfis निर्देश पर एक विस्तार है जो मैंने पथ मिलान के विभिन्न स्तरों के लिए अनुमति देने के लिए किया था। अनिवार्य रूप से मुझे एक निश्चित गहराई तक URL पथ के मिलान की आवश्यकता मिली, क्योंकि सटीक मिलान घोंसले के शिकार और डिफ़ॉल्ट पुनर्निर्देशन की अनुमति नहीं देता है। उम्मीद है की यह मदद करेगा।

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

        };
    }]);

और यहां बताया गया है कि मैं लिंक का उपयोग कैसे करता हूं

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

यह निर्देश निर्देश के लिए विशेषता मान में निर्दिष्ट गहराई स्तर से मेल खाएगा। बस इसका मतलब है कि यह कई बार खत्म हो सकता है।


1

सक्रिय लिंक को हाइलाइट करने का एक और निर्देश यहां दिया गया है।

प्रमुख विशेषताऐं:

  • Href के साथ ठीक काम करता है जिसमें गतिशील कोणीय भाव होते हैं
  • हैश-बैंग नेविगेशन के साथ संगत
  • बूटस्ट्रैप के साथ संगत जहां सक्रिय वर्ग को पैरेंट ली पर लागू किया जाना चाहिए न कि लिंक
  • यदि कोई नेस्टेड पथ सक्रिय है, तो लिंक को सक्रिय करने देता है
  • सक्रिय नहीं होने पर लिंक को अक्षम कर देता है

कोड:

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

उपयोग:

कोणीय अभिव्यक्ति के साथ सरल उदाहरण, $ गुंजाइश कहते हैं। 2. = 2 , तब लिंक सक्रिय होगा यदि स्थान / url / 2 है :

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

बूटस्ट्रैप उदाहरण, अभिभावक ली को सक्रिय वर्ग मिलेगा:

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

नेस्टेड url के साथ उदाहरण, लिंक सक्रिय होगा यदि कोई नेस्टेड url सक्रिय है (यानी / url / 1 , / url / 2 , url / 1/2 / ... )

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

जटिल उदाहरण, लिंक बिंदु एक url ( / url1 ) पर सक्रिय होगा, लेकिन यदि दूसरा चुना गया हो ( / url2 ):

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

अक्षम लिंक के साथ उदाहरण, यदि यह सक्रिय नहीं है तो यह होगा 'अक्षम' होगा वर्ग होगा:

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

सभी सक्रिय-लिंक- * विशेषताओं का उपयोग किसी भी संयोजन में किया जा सकता है, इसलिए बहुत जटिल परिस्थितियों को लागू किया जा सकता है।


1

यदि आप प्रत्येक व्यक्तिगत लिंक का चयन करने के बजाय एक आवरण में निर्देश के लिए लिंक चाहते हैं (बतरंग में गुंजाइश को देखना आसान बनाता है), तो यह बहुत अच्छा काम करता है:

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

मार्कअप बस होगा:

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

मुझे यह भी उल्लेख करना चाहिए कि मैं इस उदाहरण में 'फुल-फैट' jQuery का उपयोग कर रहा हूं, लेकिन आप आसानी से जो मैंने फ़िल्टरिंग के साथ किया है, उसे बदल सकते हैं।


1

यहाँ मेरे दो सेंट हैं, यह ठीक काम करता है।

नोट: यह चाइल्डपैज (जो मुझे चाहिए था) से मेल नहीं खाता है।

राय:

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

नियंत्रक:

// make sure you inject $location as a dependency

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

1

@Kfis के जवाब के अनुसार, यह टिप्पणी है, और मेरी सिफारिश है, नीचे के रूप में अंतिम निर्देश:

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

और यहाँ इसका उपयोग 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>

सीएसएस के साथ बाद में स्टाइल:

.active { color: red; }

1

यूआई-राउटर का उपयोग करने वालों के लिए, मेरा उत्तर कुछ हद तक Ender2050 के समान है, लेकिन मैं राज्य नाम परीक्षण के माध्यम से ऐसा करना पसंद करता हूं:

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

संगत 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

उपरोक्त निर्देश सुझावों में से कोई भी मेरे लिए उपयोगी नहीं था। यदि आपके पास बूटस्ट्रैप नौबार है जैसे

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

(है कि एक हो सकता है $ yo angularस्टार्टअप) तो आप जोड़ना चाहते हैं .activeकरने के लिए माता पिता के <li> तत्व कक्षा सूची, नहीं तत्व में ही; यानी <li class="active">..</li>। इसलिए मैंने यह लिखा:

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

उपयोग set-parent-active; .activeडिफ़ॉल्ट है इसलिए सेट करने की आवश्यकता नहीं है

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

और लिंक सक्रिय <li>होने पर मूल तत्व होगा .active.activeजैसे वैकल्पिक वर्ग का उपयोग करने के लिए .highlight, बस

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

मैंने कार्यक्षेत्र की कोशिश की थी। लेकिन यह केवल तब काम करता है जब लिंक पर क्लिक किया जाता है और 'पेज लोड पर' (रिफ्रेश बटन पर क्लिक) नहीं किया जाता है। स्थान देखना मेरे लिए काम कर रहा है
sawe

0

मेरे लिए सबसे महत्वपूर्ण सभी बूटस्ट्रैप डिफ़ॉल्ट कोड में परिवर्तन नहीं करना था। यहाँ यह मेरा मेनू कंट्रोलर है जो मेनू विकल्पों की खोज करता है और फिर जो व्यवहार हम चाहते हैं उसे जोड़ें।

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

एक ही समस्या थी। यहाँ मेरा समाधान है :

.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

मैंने इसके लिए सिर्फ एक निर्देश लिखा।

उपयोग:

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

कार्यान्वयन:

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

टेस्ट:

'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

मार्ग:

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

मेनू HTML:

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

नियंत्रक:

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

मुझे यहाँ जो समस्या है वह यह है कि मेनू आइटम केवल तभी सक्रिय होता है जब पूरा पृष्ठ लोड होता है। जब आंशिक दृश्य लोड किया जाता है तो मेनू बदलता नहीं है। किसी को पता है कि ऐसा क्यों होता है?


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

मुझे सबसे आसान उपाय मिला। बस HTML में indexOf की तुलना करने के लिए

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>
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.