Как установить активный класс начальной панели навигации с помощью Angular JS?

Если у меня есть панель навигации в начальной загрузке с элементами

Home | About | Contact

Как мне установить активный класс для каждого пункта меню, когда они активны? То есть, как я могу установить class="active", когда угловой маршрут находится в

  1. #/ для дома
  2. #/about для страницы "О нас"
  3. #/contact для страницы контактов

person user1876508    schedule 24.04.2013    source источник
comment
возможный дубликат Сделать ссылку на панели навигации Twitter Bootstrap активной   -  person givanse    schedule 26.10.2013
comment
Это похоже, но не угловой способ выделения кнопок навигации.   -  person user1876508    schedule 28.10.2013
comment
Возможный дубликат Установить активный стиль вкладки с помощью AngularJS   -  person Amit G    schedule 29.03.2017
comment
Если вы используете угловую маршрутизацию, обратите внимание, что идеальный ответ скрыт далеко внизу: stackoverflow.com/ а / 43822400/474189.   -  person Duncan Jones    schedule 25.02.2018


Ответы (26)


Очень элегантный способ - использовать ng-controller для запуска одного контроллера вне ng-view:

<div class="collapse navbar-collapse" ng-controller="HeaderController">
    <ul class="nav navbar-nav">
        <li ng-class="{ active: isActive('/')}"><a href="/">Home</a></li>
        <li ng-class="{ active: isActive('/dogs')}"><a href="/dogs">Dogs</a></li>
        <li ng-class="{ active: isActive('/cats')}"><a href="/cats">Cats</a></li>
    </ul>
</div>
<div ng-view></div>

и включите в controllers.js:

function HeaderController($scope, $location) 
{ 
    $scope.isActive = function (viewLocation) { 
        return viewLocation === $location.path();
    };
}
person myl    schedule 01.09.2013
comment
Можно ли это поместить в директиву заголовка? - person user1876508; 02.09.2013
comment
Да, конечно, может! Собственно так и сам использую :) - person myl; 02.09.2013
comment
Поскольку я новичок в этом, я был бы признателен, если бы вы могли привести пример того, как поместить это в директиву заголовка, пожалуйста. - person mono68; 20.09.2013
comment
@myl Замечательный ответ, но я просто хотел знать, что вызывает переоценку isActive ()? Дело в том, что контроллер подписывается на изменения в местоположении или, может быть, щелкнув повторно оцениваемый элемент ng-click? - person Marc M.; 04.12.2013
comment
Могут ли возникнуть проблемы из-за того, что HeaderController не добавляется в модуль контроллеров приложения? Это необходимо для этого контроллера? - person Iain; 24.03.2014
comment
ввести $location как зависимость в директиве, а затем использовать код @myl controller.js выше внутри link: в директиве. - person Danger14; 01.04.2014
comment
Я бы предложил вместо этого использовать return $location.path().indexOf(viewLocation) == 0;, чтобы вы также могли ловить страницы с параметрами - person Sven Hecht; 09.07.2014
comment
@SvenHecht Хорошее предложение, чаще всего вы хотите выделить в навигации раздел, а не отдельные страницы. - person kontur; 02.08.2014
comment
Разве использование функции в ngClass не осуждается? Считали, что лучше всего использовать переменные с ограниченным объемом? - person mtpultz; 16.09.2014
comment
Это тоже, похоже, не работает, я каждый раз отстаю на один маршрут. Мне нужно дважды щелкнуть ссылку, чтобы получить значение $ location.path, равное моему viewLocation. - person mtpultz; 16.09.2014
comment
Пока это работает. Я думаю, что контроллер не должен обрабатывать работу, связанную с пользовательским интерфейсом. Поправьте меня, если это не актуально. - person Khanetor; 22.09.2014
comment
Превосходно!! Я просто использовал $ location.url () вместо $ location.path (), чтобы включить параметры запроса. - person lsborg; 27.09.2014
comment
@myl, у меня все нормально, спасибо ,, Но мне просто нужно знать, почему вы используете фигурные скобки {..} в ng-class, а не {{...}} .. - person JS-Hero; 05.11.2014
comment
Это выполняет свою работу, но это вряд ли elegant - имя маршрута, например /dogs, должно быть продублировано при вызове isActive('/dogs') - person wal; 16.11.2014
comment
Если вы используете UI Router, вы можете использовать директивы ui-sref-active/ui-sref-active-eq, т.е. ui-sref-active-eq='active' или ui-sref-active='active' для достижения тех же результатов - person Dan; 14.04.2015
comment
@SvenHecht Проблема с этой логикой заключается в том, что ссылка на домашнюю страницу (/) будет соответствовать любому другому пути. - person mwotton; 28.04.2015
comment
@SvenHecht - mwotten верен. Проблема с этой логикой заключается в том, что ссылка на домашнюю страницу (/) будет соответствовать любому другому пути. - person Tom Stickel; 10.06.2015
comment
@DanPantry, ваш ответ сработал и намного проще, чем что-либо здесь. Спасибо! - person Batman; 18.12.2015
comment
Хотя приятно видеть реальный код, было бы неплохо увидеть небольшое объяснение кода, а не код, допускающий копирование и вставку. - person kovac; 07.08.2016
comment
@Sadeep Требование - поддерживать выбранный статус вкладки. Код делает то же самое, но "на лету". При щелчке по вкладке и изменении ее местоположения срабатывает функция класса каждой вкладки, то есть isActive (), и проверяется необходимость наличия «активного» класса. Использование контроллера - это правильный и чистый подход, как указывал Уол, код не следует за DRY. Также избыточно запускать isActive () для всех вкладок при каждом щелчке. Одна альтернатива - заставить контроллер поддерживать json-массив сведений о вкладках и выбранный индекс вкладки. При этом html может использовать ng-repeat для генерации ‹li› s в html. - person Rakesh Kumar Cherukuri; 27.10.2016
comment
Я использую ui-router, и предложение @DanPantry намного проще, если вы используете его вместе - person Bryan CS; 15.04.2017
comment
Могу ли я ввести другой класс, кроме «активного», например. {active-click: isActive ('/')}? - person Mat.Now; 26.08.2017
comment
слегка измененная версия идеально подходит для меня - ›_1 _... в зависимости от варианта использования ... - person Ruhul Amin; 08.11.2018

Я просто написал директиву для обработки этого, поэтому вы можете просто добавить атрибут bs-active-link к родительскому элементу <ul>, и каждый раз, когда маршрут изменится, он найдет соответствующую ссылку и добавит класс active к соответствующему <li>.

Вы можете увидеть это в действии здесь: http://jsfiddle.net/8mcedv3b/

Пример HTML:

<ul class="nav navbar-nav" bs-active-link>
  <li><a href="/home">Home</a></li>
  <li><a href="/contact">Contact</a></li>
</ul>

Javascript:

angular.module('appName')
.directive('bsActiveLink', ['$location', function ($location) {
return {
    restrict: 'A', //use as attribute 
    replace: false,
    link: function (scope, elem) {
        //after the route has changed
        scope.$on("$routeChangeSuccess", function () {
            var hrefs = ['/#' + $location.path(),
                         '#' + $location.path(), //html5: false
                         $location.path()]; //html5: true
            angular.forEach(elem.find('a'), function (a) {
                a = angular.element(a);
                if (-1 !== hrefs.indexOf(a.attr('href'))) {
                    a.parent().addClass('active');
                } else {
                    a.parent().removeClass('active');   
                };
            });     
        });
    }
}
}]);
person dave    schedule 04.04.2014
comment
мне это нравится больше, чем принятый ответ, потому что нет дублирования данных конфигурации, то есть сами маршруты остаются в одном месте, и это просто работает .. - person Aaron Anodide; 07.11.2015
comment
работал у меня с использованием scope. $ watch ($ routeChangeSuccess, function () {.... вместо scope. $ on ($ routeChangeSuccess, function () {.... - person aemad; 06.01.2016
comment
Пришлось немного подправить это для своих целей, но отличный ответ! Достаточно легко понять. - person Tony Anziano; 21.06.2016

Вы можете взглянуть на AngularStrap, похоже, директива navbar - это то, что вы ищете:

https://github.com/mgcrea/angular-strap/blob/master/src/navbar/navbar.js

.directive('bsNavbar', function($location) {
  'use strict';

  return {
    restrict: 'A',
    link: function postLink(scope, element, attrs, controller) {
      // Watch for the $location
      scope.$watch(function() {
        return $location.path();
      }, function(newValue, oldValue) {

        $('li[data-match-route]', element).each(function(k, li) {
          var $li = angular.element(li),
            // data('match-rout') does not work with dynamic attributes
            pattern = $li.attr('data-match-route'),
            regexp = new RegExp('^' + pattern + '$', ['i']);

          if(regexp.test(newValue)) {
            $li.addClass('active');
          } else {
            $li.removeClass('active');
          }

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

Чтобы использовать эту директиву:

  1. Загрузите AngularStrap со страницы http://mgcrea.github.io/angular-strap/.

  2. Добавьте скрипт на свою страницу после bootstrap.js:
    <script src="lib/angular-strap.js"></script>

  3. Добавьте директивы в свой модуль:
    angular.module('myApp', ['$strap.directives'])

  4. Добавьте директиву на панель навигации:
    <div class="navbar" bs-navbar>

  5. Добавьте регулярные выражения для каждого элемента навигации:
    <li data-match-route="/about"><a href="#/about">About</a></li>

person Olivier    schedule 26.04.2013
comment
Спасибо. Это помогло мне исправить мою собственную директиву (для меня отсутствующим пониманием было scope.$watch) - person Ngure Nyaga; 15.07.2013
comment
Почему переменная element передается в селектор jquery? $('...', element) - person Lucio; 04.10.2014
comment
@Lucio метод принимает 2 аргумента - jQuery (селектор, контекст) - второй аргумент - передать контекст селектора, либо родительский элемент DOM, либо сам другой объект jQuery - подробнее здесь - person CoderTR; 27.01.2015
comment
Это отлично работает для меня - однако мне пришлось внести одно изменение на mgcrea.github.io/angular- strap, добавляемая к модулю директива mgcrea.ngStrap не $strap.directives - person Vixxd; 05.01.2016

Вот простой подход, который хорошо работает с Angular.

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

В вашем контроллере AngularJS:

$scope.isActive = function (viewLocation) {
     var active = (viewLocation === $location.path());
     return active;
};
person Ender2050    schedule 06.08.2013
comment
Хороший подход. Я немного изменил его - использовал директиву ng-class (ng-class = {active: isActive ('/ View1')}) и обновил функцию isActive, чтобы она возвращала true / false вместо самого имени класса. - person patelsan; 28.08.2013
comment
Я скопировал все, как ваш пример, и для меня $ location.path () не сработал ... переключился на $ location.url (), и это сработало! - person Paulo Oliveira; 13.11.2014

Если вы работаете с маршрутизатором Angular, используйте директиву RouterLinkActive можно использовать очень элегантно:

<ul class="navbar-nav">
  <li class="nav-item"><a class="nav-link" routerLink="home" routerLinkActive="active">Home</a></li>
  <li class="nav-item"><a class="nav-link" routerLink="gallery" routerLinkActive="active">Gallery</a></li>
  <li class="nav-item"><a class="nav-link" routerLink="pricing" routerLinkActive="active">Prices</a></li>
  <li class="nav-item"><a class="nav-link" routerLink="contact" routerLinkActive="active">Contact</a></li>
</ul>
person DVarga    schedule 06.05.2017
comment
Я думаю, что это должен быть принятый ответ (по крайней мере, для angular 2+), почему что-то уже реализовано? Но для Bootstrap 3.3 класс active должен находиться в <li> (вы можете поместить routerLinkActive с routerLink или его родителем) - person PhoneixS; 12.02.2018
comment
Примечание: если вы используете / в качестве домашней страницы, routerLinkActive будет считать, что это активен для любого URL-адреса, начинающегося с /, например /foo/, /foo/bar и т. Д. Для точного совпадения нужно routerLinkActive="active" [routerLinkActiveOptions]="{exact:true}". - person Duncan Jones; 25.02.2018

Прежде всего, эту проблему можно решить разными способами. Этот способ может быть не самым элегантным, но он определенно работает.

Вот простое решение, которое вы сможете добавить в любой проект. Вы можете просто добавить pageKey или другое свойство при настройке маршрута, которое вы можете использовать для отключения. Кроме того, вы можете реализовать прослушиватель в методе $ routeChangeSuccess объекта $ route, чтобы отслеживать успешное завершение изменения маршрута.

Когда ваш обработчик запускается, вы получаете ключ страницы и используете этот ключ для поиска элементов, которые должны быть «АКТИВНЫМИ» для этой страницы, и вы применяете класс ACTIVE.

Имейте в виду, что вам нужен способ сделать ВСЕ элементы «АКТИВНЫМИ». Как видите, я использую класс .pageKey для своих элементов навигации, чтобы отключить их все, и я использую .pageKey_ {PAGEKEY} для их индивидуального включения. Переключение их всех в неактивное состояние будет считаться наивным подходом, потенциально вы могли бы повысить производительность, используя предыдущий маршрут, чтобы сделать неактивными только активные элементы, или вы могли бы изменить селектор jquery, чтобы выбрать только активные элементы, которые нужно сделать неактивными. Использование jquery для выбора всех активных элементов, вероятно, является лучшим решением, поскольку оно гарантирует, что все будет очищено для текущего маршрута в случае каких-либо ошибок css, которые могли присутствовать на предыдущем маршруте.

Это означало бы изменить эту строку кода:

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

к этому

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

Вот пример кода:

Учитывая загрузочную панель навигации

<div class="navbar navbar-inverse">
    <div class="navbar-inner">
        <a class="brand" href="#">Title</a>
        <ul class="nav">
            <li><a href="#!/" class="pagekey pagekey_HOME">Home</a></li>
            <li><a href="#!/page1/create" class="pagekey pagekey_CREATE">Page 1 Create</a></li>
            <li><a href="#!/page1/edit/1" class="pagekey pagekey_EDIT">Page 1 Edit</a></li>
            <li><a href="#!/page1/published/1" class="pagekey pagekey_PUBLISH">Page 1 Published</a></li>
        </ul>
    </div>
</div>

И угловой модуль и контроллер вроде следующего:

<script type="text/javascript">

    function Ctrl($scope, $http, $routeParams, $location, $route) {

    }



    angular.module('BookingFormBuilder', []).
        config(function ($routeProvider, $locationProvider) {
            $routeProvider.
                when('/', { 
                   template: 'I\'m on the home page', 
                   controller: Ctrl, 
                   pageKey: 'HOME' }).
                when('/page1/create', { 
                   template: 'I\'m on page 1 create', 
                   controller: Ctrl, 
                   pageKey: 'CREATE' }).
                when('/page1/edit/:id', { 
                   template: 'I\'m on page 1 edit {id}', 
                   controller: Ctrl, pageKey: 'EDIT' }).
                when('/page1/published/:id', { 
                   template: 'I\'m on page 1 publish {id}', 
                   controller: Ctrl, pageKey: 'PUBLISH' }).
                otherwise({ redirectTo: '/' });

            $locationProvider.hashPrefix("!");
        }).run(function ($rootScope, $http, $route) {

            $rootScope.$on("$routeChangeSuccess", 
                           function (angularEvent, 
                                     currentRoute,
                                     previousRoute) {

                var pageKey = currentRoute.pageKey;
                $(".pagekey").toggleClass("active", false);
                $(".pagekey_" + pageKey).toggleClass("active", true);
            });

        });

</script>
person Mark At Ramp51    schedule 24.04.2013
comment
Вам нужно прокрутить вправо, чтобы увидеть значения pageKey на маршрутах, что является ключом ко всему решению. - person Mark At Ramp51; 25.04.2013
comment
Это может сработать, но противоречит общим советам для приложений Angular.js: в Angular вы должны воздерживаться от возни с DOM с помощью jQuery; если вам нужно коснуться DOM, напишите директиву. - person Paulo Scardine; 04.06.2013
comment
это идеально, если вас беспокоит манипуляция dom, просто добавьте директиву в .navbar, добавьте событие $ broadcast в routechangesuccess, $ rootScope. $ broadcast ('routeChanged', current.pageKey); а затем зафиксируйте его в своей директиве и выполните там манипуляции с dom - person Irshu; 15.12.2014

Фактически вы можете использовать angular-ui-utils 'ui-route директива:

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

or:

Контроллер заголовка

/**
 * Header controller
 */
angular.module('myApp')
  .controller('HeaderCtrl', function ($scope) {
    $scope.menuItems = [
      {
        name: 'Home',
        url:  '/',
        title: 'Go to homepage.'
      },
      {
        name:   'About',
        url:    '/about',
        title:  'Learn about the project.'
      },
      {
        name:   'Contact',
        url:    '/contact',
        title:  'Contact us.'
      }
    ];
  });

Индексная страница

<!-- index.html: -->
<div class="header" ng-controller="HeaderCtrl">
  <ul class="nav navbar-nav navbar-right">
    <li ui-route="{{menuItem.url}}" ng-class="{active: $uiRoute}"
      ng-repeat="menuItem in menuItems">
      <a ng-href="#{{menuItem.url}}" title="{{menuItem.title}}">
        {{menuItem.name}}
      </a>
    </li>
  </ul>
</div>

Если вы используете ui-utils, вас также может заинтересовать ui-router для управления частичными / вложенными представлениями.

person Lèse majesté    schedule 14.07.2014
comment
Подход ui-route очень соблазнителен, но пока мне не удалось заставить его работать в проекте, созданном угловым генератором Йомена. - person gabuzo; 17.09.2014
comment
@gabuzo: Вы устанавливали angular -ui-utils через bower? - person Lèse majesté; 17.09.2014

Я нахожу все эти ответы немного сложными для меня, извините. Итак, я создал небольшую директиву, которая должна работать для каждой панели навигации:

app.directive('activeLink', function () {
    return {
        link: function (scope, element, attrs) {
            element.find('.nav a').on('click', function () {
                angular.element(this)
                    .parent().siblings('.active')
                    .removeClass('active');
                angular.element(this)
                    .parent()
                    .addClass('active');
            });
        }
    };
});

Использование:

<ul class="nav navbar-nav navbar-right" active-link>
    <li class="nav active"><a href="home">Home</a></li>
    <li class="nav"><a href="foo">Foo</a></li>
    <li class="nav"><a href="bar">Bar</a></li>
</ul>
person Tom Fobear    schedule 28.02.2015
comment
Ваш метод работает только после того, как вы нажмете ссылку на панели навигации. Если вы начнете с URL-адреса Foo, по-прежнему будет выбираться Home. например начиная с localhost: 9000 / # / contact, на панели навигации отображается выбранный дом. - person Adam Plocher; 23.05.2016

Для этого я использую директиву ng-class с $ location.

<ul class="nav">
<li data-ng-class="{active: ($location.path() == '/') }">
    <a href="#/">Carpeta Amarilla</a>
</li>
<li class="dropdown" data-ng-class="{active: ($location.path() == '/auditoria' || $location.path() == '/auditoria/todos') }">
    <a class="dropdown-toggle" data-toggle="dropdown" href="#">
        Auditoria
        <b class="caret"></b>
    </a>
    <ul class="dropdown-menu pull-right">
        <li data-ng-class="{active: ($location.path() == '/auditoria') }">
            <a href="#/auditoria">Por Legajo</a>
        </li>
        <li data-ng-class="{active: ($location.path() == '/auditoria/todos') }">
            <a href="#/auditoria/todos">General</a>
        </li>
    </ul>
</li>
</ul>

Для этого требуется, чтобы панель навигации находилась внутри основного контроллера с доступом к сервису $ location следующим образом:

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

Вы можете добиться этого с помощью условного выражения в угловом выражении, например:

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

При этом я считаю, что директива angular является более «правильным» способом сделать это, хотя передача большей части этой мини-логики на аутсорсинг может несколько загрязнить вашу кодовую базу.

Я время от времени использую условные обозначения для стилизации графического интерфейса во время разработки, потому что это немного быстрее, чем создание директив. Я не могу назвать вам случая, когда они действительно оставались в базе кода надолго. В конце концов, я либо превращаю это в директиву, либо нахожу лучший способ решить проблему.

person marius    schedule 30.05.2013

Если вы используете ui-router, следующий пример должен удовлетворить ваши потребности на основе @ DanPantry прокомментируйте принятый ответ без добавления кода на стороне контроллера:

<div class="collapse navbar-collapse" ng-controller="HeaderController">
    <ul class="nav navbar-nav">
        <li ui-sref-active="active"><a ui-sref="app.home()" href="/">Home</a></li>
        <li ui-sref-active="active"><a ui-sref="app.dogs()" href="/dogs">Dogs</a></li>
        <li ui-sref-active="active"><a ui-sref="app.cats()" href="/cats">Cats</a></li>
    </ul>
</div>
<div ng-view></div>

Вы можете найти в документации подробнее об этом.

person Bryan CS    schedule 15.04.2017
comment
идеально! конечно самое чистое решение - person Aryeh Beitz; 01.07.2017
comment
просто лучшее решение идёт. кто не использует ui.router! - person dewd; 30.10.2017

Если вы предпочитаете не использовать AngularStrap, то эта директива должна помочь! Это модификация https://stackoverflow.com/a/16231859/910764.

JavaScript

angular.module('myApp').directive('bsNavbar', ['$location', function ($location) {
  return {
    restrict: 'A',
    link: function postLink(scope, element) {
      scope.$watch(function () {
        return $location.path();
      }, function (path) {
        angular.forEach(element.children(), (function (li) {
          var $li = angular.element(li),
            regex = new RegExp('^' + $li.attr('data-match-route') + '$', 'i'),
            isActive = regex.test(path);
          $li.toggleClass('active', isActive);
        }));
      });
    }
  };
}]);

HTML

<ul class="nav navbar-nav" bs-navbar>
  <li data-match-route="/home"><a href="#/home">Home</a></li>
  <li data-match-route="/about"><a href="#/about">About</a></li>
</ul>

Примечание. Приведенные выше классы HTML предполагают, что вы используете Bootstrap 3.x.

person John Schult    schedule 15.04.2014

Вот мое мнение об этом. Небольшая комбинация ответов, найденных в этом посте. У меня был немного другой случай, поэтому мое решение включает в себя разделение меню на собственный шаблон, который будет использоваться в Ojbect определения директивы, а затем добавить мою панель навигации на страницу, на которой мне это нужно. По сути, у меня была страница входа в систему, на которой я не хотел включать свое меню, поэтому я использовал ngInclude и вставлял эту директиву при входе в систему:

ДИРЕКТИВА:

module.directive('compModal', function(){


return {
    restrict: 'E',
    replace: true,
    transclude: true,
    scope: true,
    templateUrl: 'templates/menu.html',
    controller: function($scope, $element, $location){
        $scope.isActive = function(viewLocation){

            var active = false;

            if(viewLocation === $location.path()){
                active = true;
            }

            return active;

        }
    }
 }
});

ДИРЕКТИВНЫЙ ШАБЛОН (templates / menu.html)

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

HTML, ВКЛЮЧАЮЩИЙ ДИРЕКТИВУ

<comp-navbar/>

Надеюсь это поможет

person britztopher    schedule 13.06.2014
comment
Функцию можно сократить до $ scope.isActive = function (viewLocation) {return viewLocation === $ location.path (); }; - person W.P. McNeill; 29.04.2015

Расширяя мой ответ, мне это нужно для обработки такой структуры.

-показатель

-events ‹-active
--- список-событий
--- редактирование-событий
--- карта-событий‹ -clicked

-места
--- список мест
--- редактирование места
--- карта мест

поэтому вместо сопоставления мне пришлось использовать indexOf, чтобы проверять дочерние ссылки, отформатированные в соответствии с условием. Итак, для «событий»:

<li ng-class="{ active: isActive('/event')}" class="divider-vertical dropdown">


function NavController($scope, $location) { 
$scope.isActive = function (viewLocation) {
    var s=false;
    if($location.path().indexOf(viewLocation) != -1){
     s = true;
    }
    return s;
};}
person M Sandoval    schedule 03.09.2013

Это простое решение

<ul class="nav navbar-nav navbar-right navbar-default menu">
  <li ng-class="menuIndice == 1 ? 'active':''">
    <a ng-click="menuIndice = 1" href="#/item1">item1</a>
  </li>
  <li ng-class="menuIndice == 2 ? 'active':''">
    <a ng-click="menuIndice = 2" href="#/item2">item2</a>
  </li>
  <li ng-class="menuIndice == 3 ? 'active':''">
    <a ng-click="menuIndice = 3" href="#/item3">item3</a>
  </li>
</ul>
person Marcelo Fernandez    schedule 18.11.2015

В сочетании с ответом @Olivier AngularStrap я также реализовал ответ Кевинкнельсона из: https://github.com/twbs/bootstrap/issues/9013.

Изначально панель навигации Bootstrap3 не была предназначена для одностраничного (например, Angular) приложения, и поэтому меню на маленьком экране не сворачивалось при нажатии.

person Tim S.    schedule 19.09.2013

JavaScript

/**
 * Main AngularJS Web Application
 */

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


/**
 * Setup Main Menu
 */

app.controller('MainNavCtrl', [ '$scope', '$location', function ( $scope, $location) {
    $scope.menuItems = [
        {
            name: 'Home',
            url:  '/home',
            title: 'Welcome to our Website'
        },
        {
            name: 'ABOUT',
            url:  '/about',
            title: 'Know about our work culture'
        },
        {
            name:   'CONTACT',
            url:    '/contact',
            title:  'Get in touch with us'
        }
    ];

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

HTML

  <div class="navbar-collapse collapse" ng-controller="MainNavCtrl">
    <ul id="add-magic-line" class="nav navbar-nav navbar-right">
      <li data-ng-class="{current_page_item: isActive('{{ menuItem.url }}')}" data-ng-repeat="menuItem in menuItems">
        <a data-ng-href="#{{menuItem.url}}" title="{{menuItem.title}}">
          {{menuItem.name}}
        </a>
      </li>
    </ul>
  </div>
person Syed    schedule 18.10.2014
comment
Это не работает - он не добавляет текущий класс в DOM - person TheBlackBenzKid; 18.10.2015

Спасибо @Pylinux. Я использовал его технику, а также модифицировал ее для поддержки «одного» уровня выпадающего меню (sub ul / li), так как это то, что мне было нужно. Посмотрите его в действии по ссылке ниже.

Обновленный Fiddle на основе ответа pylinux - http://jsfiddle.net/abhatia/en4qxw6g/

Я внес следующие три изменения, чтобы поддерживать одноуровневое раскрывающееся меню:
1. Добавлено значение класса dd (раскрывающееся меню) для элемента «a» в li, который должен иметь список sub ul.

         <li><a class="dd">This link points to #/fun5</a>
          <ul>
            <li><a href="#/fun6?some=data">This link points to #/fun6</a>
            </li>
            <li><a href="#/fun7?some=data">This link points to #/fun7</a>
            </li>
            <li><a href="#/fun8?some=data">This link points to #/fun8</a>
            </li>
            <li><a href="#/fun9?some=data">This link points to #/fun9</a>
            </li>
          </ul>
        </li>


2. Обновлен Javascript, чтобы добавить следующую новую логику.

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


3. Обновлен CSS, чтобы добавить следующее:

a.active {background-color:red;}

Надеюсь, это будет полезно для тех, кто хочет реализовать одноуровневое раскрывающееся меню.

person abhishek    schedule 26.05.2016

Используйте объект в качестве переменной-переключателя.
Вы можете сделать это очень просто с помощью:

<ul class="nav navbar-nav">
   <li ng-class="{'active':switch.linkOne}" ng-click="switch = {linkOne: true}"><a href="/">Link One</a></li>
   <li ng-class="{'active':switch.linkTwo}" ng-click="switch = {link-two: true}"><a href="/link-two">Link Two</a></li>
</ul>

Каждый раз, когда вы щелкаете ссылку, объект-переключатель заменяется новым объектом, в котором истинно только правильное свойство объекта-переключателя. Неопределенные свойства будут оцениваться как ложные, поэтому элементам, которые от них зависят, не будет назначен активный класс.

person Dario Mincioni    schedule 20.01.2019

Вы также можете использовать эту директиву активной ссылки https://stackoverflow.com/a/23138152/1387163

Родительский li получит активный класс при совпадении местоположения / url:

<li>
    <a href="#!/url" active-link active-link-parent>
</li>
person Eugene Fidelin    schedule 17.04.2014

Я предлагаю использовать директиву по ссылке. Вот скрипка.

Но это еще не идеально. Остерегайтесь хэшбэгов;)

Вот директива 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);
          }
        });
      }
    };
  }]);

и вот как это будет использоваться в 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; }
person Kalpesh Prajapati    schedule 06.07.2014

Чтобы добавить свои два цента в дискуссию, я создал чистый угловой модуль (без 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);
            }
        }
    }]);
}());

* (Вы, конечно, можете просто использовать директивную часть)

** Также стоит отметить, что это не работает для пустых хэшей (ig example.com/# или просто example.com) он должен иметь хотя бы example.com/#/ или просто example.com#/. Но это происходит автоматически с ngResource и т.п.

person Pylinux    schedule 28.07.2014
comment
Это просто мерзко. Причина использования Angular - простота. - person Tom Stickel; 10.06.2015

Это помогло мне:

  var domain = '{{ DOMAIN }}'; // www.example.com or dev.example.com
  var domain_index =  window.location.href.indexOf(domain);
  var long_app_name = window.location.href.slice(domain_index+domain.length+1); 
  // this turns http://www.example.com/whatever/whatever to whatever/whatever
  app_name = long_app_name.slice(0, long_app_name.indexOf('/')); 
  //now you are left off with just the first whatever which is usually your app name

то вы используете jquery (также работает с angular), чтобы добавить активный класс

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

и, конечно же, css:

.active{background:red;}

это работает, если у вас есть такой HTML:

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

это автоматически добавит активный класс, используя URL-адрес страницы, и закрасит ваш фон в красный цвет, если ваш в www.somesite.com/ee thaen ee является `` приложением '', и он будет активен

person elad silver    schedule 02.07.2014

На это длинный ответ, но я подумал, что поделюсь своим путем:

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

Шаблон:

<ul class="nav navbar-nav">
    <li ng-class="{ active: $state.contains('View1') }"><a href="...">View 1</a></li>
    <li ng-class="{ active: $state.contains('View2') }"><a href="...">View 2</a></li>
    <li ng-class="{ active: $state.contains('View3') }"><a href="...">View 3</a></li>
</ul>

Для тех, кто использует ui-router:

<ul class="nav navbar-nav">
        <li ui-sref-active="active"><a href="...">View 1</a></li>
        <li ui-sref-active="active"><a href="...">View 2</a></li>
        <li ui-sref-active="active"><a href="...">View 3</a></li>
</ul>

Для точного совпадения (например, вложенных состояний?) Используйте $state.name === 'full/path/to/state' или ui-sref-active-eq="active"

person Muli Yulzary    schedule 05.07.2016

Вот еще одно решение для всех, кому это может быть интересно. Преимущество этого в том, что у него меньше зависимостей. Черт возьми, он работает и без веб-сервера. Так что это полностью на стороне клиента.

HTML:

<nav class="navbar navbar-inverse" ng-controller="topNavBarCtrl"">
<div class="container-fluid">
    <div class="navbar-header">
        <a class="navbar-brand" href="#"><span class="glyphicon glyphicon-home" aria-hidden="true"></span></a>
    </div>
    <ul class="nav navbar-nav">
        <li ng-click="selectTab()" ng-class="getTabClass()"><a href="#">Home</a></li>
        <li ng-repeat="tab in tabs" ng-click="selectTab(tab)" ng-class="getTabClass(tab)"><a href="#">{{ tab }}</a></li>
    </ul>
</div>

Explanation:

Здесь мы динамически генерируем ссылки из модели angularjs с помощью директивы ng-repeat. Волшебство происходит с методами selectTab() и getTabClass(), определенными в контроллере для этой панели навигации, представленной ниже.

Контроллер:

angular.module("app.NavigationControllersModule", [])

// Constant named 'activeTab' holding the value 'active'. We will use this to set the class name of the <li> element that is selected.
.constant("activeTab", "active")

.controller("topNavBarCtrl", function($scope, activeTab){
    // Model used for the ng-repeat directive in the template.
    $scope.tabs = ["Page 1", "Page 2", "Page 3"];

    var selectedTab = null;

    // Sets the selectedTab.
    $scope.selectTab = function(newTab){
       selectedTab = newTab;
    };

    // Sets class of the selectedTab to 'active'.
    $scope.getTabClass = function(tab){
       return selectedTab == tab ? activeTab : "";
    };
});

Объяснение:

selectTab() метод вызывается с помощью директивы ng-click. Поэтому при нажатии на ссылку переменная selectedTab устанавливается равной имени этой ссылки. В HTML вы можете видеть, что этот метод вызывается без каких-либо аргументов для вкладки «Главная», поэтому он будет выделен при загрузке страницы.

Метод getTabClass() вызывается директивой ng-class в HTML. Этот метод проверяет, совпадает ли вкладка, на которой он находится, со значением переменной selectedTab. Если true, он возвращает «active», иначе возвращает «», который применяется в качестве имени класса директивой ng-class. Тогда любой css, который вы применили к классу active, будет применен к выбранной вкладке.

person kovac    schedule 07.08.2016
comment
Что случилось, я перехожу на другую вкладку любым другим способом? - person Miguel Carvajal; 16.10.2016
comment
Что ты имеешь в виду? - person kovac; 16.10.2016
comment
например, ссылка на странице, которая переводит вас на другую страницу, которая находится внутри другой вкладки. Имеет смысл? - person Miguel Carvajal; 16.10.2016
comment
В этом случае я думаю, что лучше использовать ui-router, как это было предложено Мули Юлзары в ответе выше. ui-router назначает состояние каждому URL-адресу. Итак, как только кто-то щелкнет ссылку, пользователь будет перенаправлен на эту ссылку, и состояние приложения angular будет обновлено. Затем ui-sref = active выделит вкладку. Вот документация для angular 2: ui-router.github.io/ng2. Кроме того, вместо использования обычной начальной загрузки посмотрите на UI Bootstrap, созданный для использования с приложениями Angular. Начальная загрузка пользовательского интерфейса: angular-ui.github.io/bootstrap - person kovac; 16.10.2016

Просто вам нужно будет добавить требуемый active-класс с нужным цветовым кодом.

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

person Shankar Gangadhar    schedule 30.10.2016