현재 메뉴 항목을 강조 표시하는 방법


205

AngularJS active는 현재 페이지의 링크 에서 클래스를 설정하는 데 어떤 도움을 줍니까 ?

나는 이것이 행해지는 마법의 방법이 있다고 생각하지만 찾을 수없는 것 같습니다.

내 메뉴는 다음과 같습니다

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

그리고 나는 나의 경로에있는 그들 각각의 컨트롤러를 가지고 TasksControllerActionsController.

그러나 a컨트롤러 에 대한 링크 에서 "active"클래스를 바인딩하는 방법을 알 수 없습니다 .

힌트가 있습니까?

답변:


265

보기에

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

컨트롤러에서

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

이를 통해 작업 링크에는 '/ tasks'(예 : '/ tasks / 1 / reports')로 시작하는 모든 URL에 활성 클래스가 있습니다.


4
"/"및 "/ anything"둘 다 일치하거나 "/ test", "/ test / this", "/ test / this / path"와 같이 비슷한 URL을 가진 여러 메뉴 항목이있는 경우 / test, 모든 옵션을 강조 표시합니다.
Ben Lesh

3
나는 ($ location.path () == path)이고 y 경로가 "/ blah"등으로 변경했습니다
Tim

113
나는 표기 선호 ngClass="{active: isActive('/tasks')}, isActive()이 컨트롤러와 마크 업 / 스타일을 디커플링으로 부울을 반환합니다.
Ed Hinchliffe

6
경로가 "/"인 경우 코드가 두 배로 늘어나지 않을지 궁금해하는 사람을 위해, 이것은 형식화에 대해 죄송합니다. $ scope.getClass = function (path) {if ($ location.path (). substr (0, path.length) == path) {if (path == "/"&& $ location.path () == "/") {return "active"; } else if (path == "/") {return ""; } "active"반환} else {return ""}}

1
EdHinchliffe는 이미 이것이 마크 업과 논리를 혼합한다고 지적했습니다. 또한 경로가 중복되어 복사 및 붙여 넣기 오류가 발생하기 쉽습니다. 더 많은 줄이 있지만 @kfis의 지시어 접근 방식이 더 재사용 가능하고 마크 업을 깨끗하게 유지한다는 것을 알았습니다.
A. Murray

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>

이후 CSS로 스타일링하기 :

.active { color: red; }

"해시 뱅 조심"이라는 것이 무슨 의미인지 잘 모르겠습니다. 항상 작동하는 것 같습니다. 반례를 제시해 주시겠습니까?
Andriy Drozdyuk 4

7
부트 스트랩을 사용하려고하는데 li 내의 a href의 해시를 기반으로 설정 해야하는 경우을 사용하십시오 var path = $(element).children("a")[0].hash.substring(1);. 이것은 다음과 같은 스타일에서 작동합니다<li active-link="active"><a href="#/dashboard">Dashboard</a></li>
Dave

2
로 바꿨 scope.$watch('location.path()', function(newPath) {습니다 scope.$on('$locationChangeStart', function(){.
sanfilippopablo

2
당신이 겨-HREF를 사용하는 경우 단지 변경 : var path = attrs.href;var path = attrs.href||attrs.ngHref;
윌리엄 닐리

Bootstrap을 사용하고에 활성 클래스를 배치해야하는 경우 다음과 같이 <li>변경할 수 있습니다 element.addClass(clazz);.element.parent().addClass(clazz);
JamesRLamar

47

다음은 Angular와 잘 작동하는 간단한 접근 방식입니다.

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

이 스레드에는 다른 유사한 답변이 많이 있습니다.

Angular JS로 부트 스트랩 navbar 활성 클래스를 설정하는 방법은 무엇입니까?


1
불필요한 변수를 제거하십시오. 비교 결과를 반환하십시오. return viewLocation === $location.path()
afarazit

33

토론에 내 두 센트를 추가하기 위해 순수한 각도 모듈 (jQuery 없음)을 만들었으며 데이터가 포함 된 해시 URL 과도 작동합니다. (예를 들어 #/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
훌륭한 솔루션이지만 앱이 실행되는 동안 locationChange에서만 초기 페이지로드에서 작동하지 않았습니다. 처리하기 위해 스 니펫 을 업데이트 했습니다.
Jerry

@Jarek : 감사합니다! 변경 사항을 구현했습니다. 나는 개인적으로 이것에 문제가 없었지만, 당신의 해결책은이 문제에 직면 해야하는 사람들에게 좋은 안정된 해결책처럼 보입니다.
Pylinux

2
다른 사람이 어떤 좋은 아이디어가 있다면 지금은 풀 요청에 대한 Github에서의 환매 특약을 만들었습니다 github.com/Karl-Gustav/autoActive
Pylinux

방금 ng-href를 사용하는 경우 발생할 수있는 몇 가지 버그를 수정했습니다. github.com/Karl-Gustav/autoActive/pull/3
Blake Niemyjski

이 스크립트를 사용하여 다른 요소를 활성화 할 수 있도록 경로를 지정할 수 있다면 좋을 것입니다.
Blake Niemyjski

22

내 경우에는 탐색을 담당하는 간단한 컨트롤러를 만들어서이 문제를 해결했습니다.

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

그리고 ng-class를 요소에 다음과 같이 추가하면됩니다.

<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-router 지시문이며 내장 라우터 인 일명 ngRoute를 사용하면 작동하지 않습니다. 즉, UI 라우터는 훌륭합니다.
moljac024

동의합니다. 원래는 ui-router 전용 솔루션이라는 것을 언급하지 않았습니다.
frankie4fingers

13

ng-class변수와 CSS 클래스를 바인딩 하는 지시문 이 있습니다 . 또한 객체 (className 대 bool 값 쌍)도 허용합니다.

예를 들면 다음과 같습니다. http://plnkr.co/edit/SWZAqj


고맙지 만, 다음과 같은 경로에서는 작동하지 /test1/blahblah않습니까?
Andriy Drozdyuk

그렇다면 active: activePath=='/test1'자동으로 "active"를 반환 한다는 것은 주어진 문자열로 경로가 시작 된다는 것 입니까? 이것은 일종의 사전 정의 된 연산자 또는 정규식입니까?
Andriy Drozdyuk

죄송합니다. 귀하의 요구 사항을 올바르게 이해했다고 생각하지 않습니다. 여기에 새로운 추측이 있습니다. 경로가 'test1 / blahblah'일 때 'test1'링크와 'test1 / blahblah'링크를 강조 표시하고 싶습니다. "맞습니까? 작동합니다.
토시

3
다음은 대체 솔루션을 보여주기 위해 업데이트 된 plnkr : plnkr.co/edit/JI5DtK (추정 된 요구 사항을 충족)입니다.
Tosh

난 당신이 무슨 짓을했는지 참조. 그러나 나는 ==HTML에서 반복 검사를 좋아하지 않습니다 .
Andriy Drozdyuk 4

13

@ Renan-tomal-fernandes 의 답변 은 좋지만 올바르게 작동하려면 몇 가지 개선이 필요했습니다. 그랬듯이 다른 섹션에 있더라도 항상 홈페이지 (/)에 대한 링크가 트리거 된 것으로 감지됩니다.

그래서 조금 개선했습니다. 코드는 다음과 같습니다. 나는 작업 부트 스트랩 활성 부분은에 그래서 <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

위의 훌륭한 제안 중 일부를 읽은 후에 생각해 낸 해결책은 다음과 같습니다. 특정 상황에서 부트 스트랩 탭 구성 요소 를 메뉴로 사용하려고 했지만 각 탭을 북마크 할 수있는 메뉴로 탭을 사용하기 때문에 Angular-UI 버전을 사용하고 싶지 않았습니다. 단일 페이지의 탐색 역할을하는 탭이 아니라 부트 스트랩 탭의 Angular-UI 버전에 관심이있는 경우 http://angular-ui.github.io/bootstrap/#/tabs를 참조하십시오 .

나는 이것을 처리하기 위해 자신의 지시문을 만드는 것에 대한 kfis의 답변을 정말로 좋아했지만 모든 단일 링크에 배치 해야하는 지시문을 갖는 것은 번거로운 것처럼 보였습니다. 그래서 대신에 한 번 배치되는 자체 Angular 지시문을 만들었습니다 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" : "";
  };
});


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>

음 ... 이것은 받아 들여지는 대답보다 더 복잡해 보입니다. 이것보다 장점을 설명해 주시겠습니까?
Andriy Drozdyuk 4

1
메뉴가 ng-view 외부에있는 시나리오에서 필요합니다. View 컨트롤러는 외부에 액세스 할 수 없으므로 $ rootScope를 사용하여 통신을 활성화했습니다. 메뉴가 ng-view 안에 있으면이 솔루션을 사용하면 아무런 이점이 없습니다.
mrt

4

Bootstrap 4.1과 함께 Angular 버전 6 사용

나는 아래와 같이 그것을 할 수있었습니다.

아래 예에서 URL에 '/ contact'가 표시되면 부트 스트랩 활성이 html 태그에 추가됩니다. URL이 변경되면 제거됩니다.

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

이 지시문을 사용하면 링크의 경로가 활성화 될 때 CSS 클래스를 요소에 추가 할 수 있습니다.

Angular 웹 사이트에서 더 읽기


3

지시어를 사용하면 (여기서는 DOM 조작을 수행하기 때문에) 다음과 같은 작업이 "각도"에 가장 가깝습니다.

$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>것이 더 좋을지 모르지만 그것이 가능한지 확실하지 않습니다.
Andriy Drozdyuk

정적 인 비 순차 목록 대신 최신 버전으로 업데이트했습니다. 이제 Boostrap 드롭 다운 메뉴를 선택 목록으로 사용하고 있습니다.
웨슬리 헤일 즈

이것은 관용적 각도와 가장 비슷해 보입니다. stackoverflow.com/questions/14994391/…에 제공된 조언과 일치하는 것으로 보이며 뷰, href 및 ng-class에서 경로가 중복되는 것을 피합니다.
fundead

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

이를 통해 track-active 지시문이있는 섹션에 링크를 만들 수 있습니다.

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

용법:

각도 표현을 사용한 간단한 예에서 $ scope.var = 2 라고 말한 다음 location이 / url / 2 인 경우 링크가 활성화됩니다 .

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

부트 스트랩 예제, 부모 li은 활성 클래스를 얻습니다.

<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 )을 가리 키지 만 다른 URL ( / url2 )을 선택하면 활성화됩니다 .

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

링크가 비활성화 된 예, 활성화되어 있지 않으면 '비활성화' 클래스가됩니다.

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

모든 active-link- * 속성은 어떤 조합으로도 사용할 수 있으므로 매우 복잡한 조건을 구현할 수 있습니다.


1

각 개별 링크를 선택하지 않고 랩퍼에서 지시문에 대한 링크를 원한다면 (Batarang의 범위를 쉽게 볼 수 있습니다), 이것은 꽤 잘 작동합니다.

  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>

이후 CSS로 스타일링하기 :

.active { color: red; }

1

ui-router를 사용하는 사람들의 경우 내 대답은 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>

scope. $ on ( "$ routeChangeSuccess", function (event, current, previous) {applyActiveClass ();});을 시도했습니다. 그러나 '페이지로드시'가 아닌 링크를 클릭 할 때만 작동합니다 (새로 고침 버튼 클릭). 위치가 나를 위해 일한 것을보고
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>
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.