Як встановити активний клас bootstrap navbar з Angular JS?


306

Якщо я маю навбар у завантажувальній програмі з елементами

Home | About | Contact

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

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

можливий дублікат
активізації

10
Це схоже, але не є "кутовим способом" підсвічування навігаційних кнопок.
користувач1876508


Якщо ви використовуєте кутову маршрутизацію , зауважте, що ідеальна відповідь зафіксована нижче: stackoverflow.com/a/43822400/474189 .
Дункан Джонс

Відповіді:


598

Дуже елегантний спосіб - використовувати ng-контролер для запуску одного контролера поза межами ng-перегляду:

<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')
вали

7
Якщо ви використовуєте маршрутизатор UI, то ви можете використовувати ui-sref-active/ui-sref-active-eqдирективи, тобто. ui-sref-active-eq='active'або ui-sref-active='active'для досягнення тих же результатів
Dan Pantry

10
@SvenHecht Заклопотаність у цій логіці полягає в тому, що посилання на домашню сторінку (/) відповідатиме кожному іншому шляху.
mwotton

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
працював для мене, використовуючи область. $ watch ("$ routeChangeSuccess", функція () {.... замість області. $ on ("$ routeChangeSuccess", функція () {....
aemad

Довелося трохи підправити це для моїх власних цілей, але приголомшлива відповідь! Досить просто зрозуміти.
Тоні Анзіано

38

Ви можете подивитися на AngularStrap , начебто, саме ви шукаєте директиву навігації:

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

@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 замість самого імені класу.
patelsan

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

14

Якщо ви працюєте з кутовим маршрутизатором, директиву 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, щоб прослухати успішне завершення зміни маршруту.

Коли ваш обробник спрацьовує, ви отримуєте ключ сторінки та використовуйте цей ключ, щоб знайти елементи, які повинні бути "АКТИВНІ" для цієї сторінки, і ви застосуєте клас АКТИВНІ.

Майте на увазі, що вам потрібен спосіб зробити ВСІ елементи "В АКТИВНОМУ". Як ви бачите, я використовую клас .pageKey на моїх елементах nav, щоб їх вимкнути, і я використовую .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 на маршрутах, ось ключ до всього цього рішення.
Позначити в Рамп51

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

це ідеально, якщо маніпуляція з домом турбує вас, просто додайте директиву на .navbar, додайте події $ трансляції у 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-роутер для управління частковими / вкладеними представленнями.


Підхід у маршруті дуже спокусливий, але поки що мені не вдалося змусити його працювати над проектом, створеним кутовим генератором Yeoman.
габузо

@gabuzo: Ви встановили angular-ui-utils через bower?
Lèse majesté

6

Я вважаю всі ці відповіді трохи складнішими для мене, вибачте. Тому я створив невелику директиву, яка повинна працювати на принципі per navbar:

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", "Home" спочатку буде вибрано як і раніше. наприклад, починаючи з localhost: 9000 / # / contact приводить до вибору Home на панелі навігації.
Адам Плочер

5

Я використовую директиву ng-класу з $ 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>

Він вимагає, щоб навибар знаходився в головному контролері з доступом до служби розміщення $ таким чином:

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>

Зважаючи на це, я вважаю, що кутова директива є більш "правильним" способом її виконання, навіть якщо аутсорсинг багато цієї міні-логіки може дещо забруднити вашу кодову базу.

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


4

Якщо ви використовуєте ui-роутер , наступний приклад повинен задовольнити ваші потреби на основі коментаря @ 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>

Ви можете перевірити документи, щоб отримати більше інформації про них.


ідеально! безумовно, найчистіше рішення
Aryeh Beitz

просто просто найкраще рішення. хто не використовує 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

Ось мій взяти на це. Трохи поєднання відповідей, знайдених у цій публікації. У мене був дещо інший випадок, тому моє рішення передбачає відокремлення меню на свій власний шаблон, який буде використовуватися в рамках визначення директиви 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;

        }
    }
 }
});

ДИРЕКТИВНА ТЕМПЛАТА (шаблони / 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
Функцію можна скоротити лише до $ range.isActive = функція (viewLocation) {return viewLocation === $ location.path (); };
WP McNeill

2

Розширюючи свою відповідь, мені знадобилося це для обробки такої структури.

-індекс

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

-places
--- place-list
--- place-edit
--- place-map

тому замість відповідності мені довелося використовувати 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

У поєднанні з відповіддю AngularStrap @ Олів’є я також реалізував відповідь кевінкнелсона з: https://github.com/twbs/bootstrap/isissue/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, який повинен мати додатковий список.

         <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

Я пропоную використовувати директиву за посиланням. Ось скрипка.

Але це ще не ідеально. Слідкуйте за хешбагами;)

Ось 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), і він також буде працювати з хеш-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);
            }
        }
    }]);
}());

* (Звичайно, ви можете просто скористатися директивою)

** Також варто зауважити, що це не працює для порожніх хешів ( 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 (також працює з кутовим), щоб додати клас активний

$('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 - це «додаток», і він буде активним


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 ви бачите, що цей метод викликається без будь-якого аргументу для вкладки «Головна», щоб він був виділений під час завантаження сторінки.

getTabClass()Метод викликається з допомогою ng-classдирективи в HTML. Цей метод перевіряє, чи вкладка, на якій він знаходиться, така ж, як і значення selectedTabзмінної. Якщо вірно, він повертає "active" else return "", який застосовується як назва класу за ng-classдирективою. Тоді те, що ви застосували до класу css, activeбуде застосовано до вибраної вкладки.


Що трапляється, я переходжу до іншої вкладки будь-яким іншим способом?
Мігель Карвахаль

Що ви маєте на увазі?
ковач

наприклад, посилання на сторінці, яка перенаправляє вас на іншу сторінку, що знаходиться на іншій вкладці. Має сенс?
Мігель Карвахаль

У цьому випадку я думаю, що краще використовувати ui-роутер, як запропонував Мулі Юлзарі у відповіді вище. ui-роутер призначає стан для кожної URL-адреси. Отже, як тільки хтось натисне на посилання, користувач буде перенаправлений на це посилання, і стан кутової програми буде оновлено. Тоді ui-sref = "active" виділить вкладку. Ось документація для кутового 2: ui-router.github.io/ng2 . Крім того, замість звичайної завантажувальної програми, подивіться на UI Bootstrap, зроблений для використання з кутовими програмами. UI Bootstrap: angular-ui.github.io/bootstrap
kovac

0

Просто вам доведеться додати необхідний activeклас із необхідним кольоровим кодом.

Наприклад: ng-class="{'active': currentNavSelected}" ng-click="setNav"

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.