Как установить загрузочный класс Navbar с Angular JS?


306

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

Home | About | Contact

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

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

возможно дублирование активной ссылки Twitter Twitter Bootstrap
givanse

10
Это похоже, но не является «угловым способом» выделения кнопок навигации.
user1876508


Если вы используете угловую маршрутизацию , обратите внимание, что идеальный ответ скрыт ниже: stackoverflow.com/a/43822400/474189 .
Дункан Джонс

Ответы:


598

Очень элегантный способ - использовать 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();
    };
}

10
Поскольку я новичок в этом, я был бы признателен, если бы вы могли привести пример того, как поместить это в директиву заголовка, пожалуйста.
mono68

41
Я бы предложил использовать return $location.path().indexOf(viewLocation) == 0;вместо этого, чтобы вы могли поймать страницы с параметрами, а также
Свен Хехт

7
Это делает работу, но ее трудно elegant- название маршрута, например /dogs, должно быть продублировано во время звонкаisActive('/dogs')
wal

7
Если вы используете UI Router, то вы можете использовать ui-sref-active/ui-sref-active-eqдирективы, т.е. ui-sref-active-eq='active'или ui-sref-active='active'для достижения тех же результатов
Дэн Пантри

10
@SvenHecht Проблема с этой логикой заключается в том, что ссылка на домашнюю страницу (/) будет соответствовать любому другому пути.
Мвоттон

51

Я просто написал директиву для этого, так что вы можете просто добавить атрибут 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');   
                };
            });     
        });
    }
}
}]);

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

1
работал для меня с использованием scope. $ watch ("$ routeChangeSuccess", function () {.... вместо scope. $ on ("$ routeChangeSuccess", function () {....
aemad

Пришлось немного подправить это для моих собственных целей, но потрясающий ответ! Достаточно легко понять.
Тони Анциано

38

Вы можете взглянуть на 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>


1
Спасибо. Это помогло мне исправить мою собственную директиву (недостающее понимание для меня было scope.$watch)
Нгуре Няга

Почему elementпеременная передается в селектор jquery? $('...', element)
Лусио

@Lucio метод принимает 2 аргумента - jQuery (селектор, контекст) - вторым аргументом является передача контекста селектора, либо родительского элемента DOM, либо самого другого объекта jQuery - подробнее здесь
CoderTR

Это прекрасно работает для меня - я должен был сделать одно изменение, однако, за mgcrea.github.io/angular-strap директива, которую добавить в ваш модуль, mgcrea.ngStrapнет$strap.directives
Vixxd

33

Вот простой подход, который хорошо работает с 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;
};

2
Хороший подход. Я немного его изменил - использовал директиву ng-class (ng-class = {active: isActive ('/ View1')}) и обновил функцию isActive, чтобы она возвращала true / false вместо самого имени класса.
Пателсан

Я скопировал все, как в вашем примере, и у меня $ location.path () не сработал ... переключился на $ location.url (), и это сработало!
Пауло Оливейра

14

Если вы работаете с Angular router, директива 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>

2
Я думаю, что это должен быть принятый ответ (по крайней мере для угловых 2+), почему реализовать что-то уже реализовано? Но для Bootstrap 3.3 activeкласс должен быть в <li>(вы можете поместить routerLinkActive с routerLink или его родителем)
PhoneixS

3
Примечание: если вы используете в /качестве домашней страницы, routerLinkActiveбудет считать, что активным для любого URL, начиная с /, например /foo/, /foo/barи т. Д. Для точного соответствия вам нужно routerLinkActive="active" [routerLinkActiveOptions]="{exact:true}".
Дункан Джонс

8

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

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

Когда ваш обработчик запускается, вы получаете ключ страницы и используете этот ключ, чтобы найти элементы, которые должны быть «ACTIVE» для этой страницы, и вы применяете класс 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>

Вам нужно прокрутить вправо, чтобы увидеть значения pageKey на маршрутах, это ключ ко всему этому решению.
Марк на Ramp51

16
Это может работать, но противоречит общему совету для приложений Angular.js: в Angular вы должны воздерживаться от работы с DOM с помощью jQuery; если вам нужно дотронуться до DOM, напишите директиву.
Пауло Скардин

Это прекрасно, если манипуляция dom вас беспокоит, просто добавьте директиву на .navbar, добавьте событие $ broadcast в routechangesuccess, $ rootScope. $ broadcast ('routeChanged', current.pageKey); а затем запишите это в вашу директиву и сделайте там манипуляции с
домом

7

Вы можете использовать угловую-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>

или:

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

/**
 * 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 для управления частичными / вложенными представлениями.


Подход ui-route очень соблазнителен, но до сих пор мне не удалось заставить его работать над проектом, сгенерированным угловым генератором Йомана.
Габузо

@gabuzo: Вы устанавливали angular-ui-utils через беседку?
Lèse Majesté

6

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

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>

Ваш метод работает только после нажатия на ссылку в навигационной панели. Если вы начинаете с URL-адреса «Foo», изначально будет выбран «Домой». например, запуск с локального хоста: 9000 / # / contact заставляет Home быть выбранным в навигационной панели.
Адам Плохер

5

Я использую директиву 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;
}]);

4

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

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

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

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


4

Если вы используете 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>

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


идеальный! безусловно, самое чистое решение
Арье

Просто самое лучшее решение. кто не использует ui.router!
роса

3

Если вы не хотите использовать 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


3

Вот мой взгляд на это. Небольшая комбинация ответов найдена на этом посте. У меня был немного другой случай, поэтому мое решение заключается в разделении меню на собственный шаблон, который будет использоваться в объекте определения директивы, а затем добавление панели навигации на страницу, на которой оно мне было необходимо. По сути, у меня была страница входа, на которую я не хотел включать свое меню, поэтому я использовал 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/>

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


1
Функция может быть сокращена до $ scope.isActive = function (viewLocation) {return viewLocation === $ location.path (); };
WP McNeill

2

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

-индекс

-events <-active
--- список
событий --- event-edit
--- карта событий <-clicked

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

поэтому вместо сопоставления мне пришлось использовать 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;
};}

2

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

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

1

Вместе с ответом @ Olivier's AngularStrap я также реализовал ответ kevinknelson по адресу : https://github.com/twbs/bootstrap/issues/9013 .

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


1

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>

Это не работает - он не добавляет текущий класс в DOM
TheBlackBenzKid

1

Благодаря @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;}

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


1

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

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

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



0

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

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

Вот 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; }

0

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


Это просто противно. Причина использования Angular для простоты.
Том Стиккель

0

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

  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 тоже), чтобы добавить класс Active

$('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>

это автоматически добавит класс active с помощью URL-адреса страницы и раскрасит фон в красный, если на www.somesite.com/ee thaen ee указано «app», и оно будет активным.


0

Это давно ответили, но я думал, что поделюсь своим путем:

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


0

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

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>

Объяснение:

Здесь мы генерируем ссылки динамически из модели 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 вы можете видеть, что этот метод вызывается без каких-либо аргументов для вкладки Home, поэтому он будет выделен при загрузке страницы.

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


Что происходит, когда я перехожу на другую вкладку каким-либо другим способом?
Мигель Карвахаль

Что вы имеете в виду?
Ковач

например, ссылка на странице, которая ведет вас на другую страницу, которая находится в другой вкладке. Имеет смысл?
Мигель Карвахаль

В этом случае я думаю, что лучше использовать ui-router, как предложено Muli Yulzary в ответе выше. ui-router назначает состояние каждому URL. Поэтому, когда кто-то щелкнет по ссылке, пользователь будет перенаправлен на эту ссылку, и состояние углового приложения будет обновлено. Тогда ui-sref = "active" выделит вкладку. Вот документация для угловых 2: ui-router.github.io/ng2 . Кроме того, вместо использования обычной начальной загрузки взгляните на UI Bootstrap, созданный для использования с приложениями Angular. UI Bootstrap: angular-ui.github.io/bootstrap
Ковач

0

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

Пример: ng-class="{'active': currentNavSelected}" ng-click="setNav"

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.