如何使用Angular JS设置bootstrap navbar活动类?

use*_*508 306 javascript navbar twitter-bootstrap angularjs angularjs-directive

如果我在引导程序中有一个带有项目的导航栏

Home | About | Contact
Run Code Online (Sandbox Code Playgroud)

如何为每个菜单项激活时设置活动类?也就是说,如何设置class="active"角度路径的时间

  1. #/ 为了家
  2. #/about 对于关于页面
  3. #/contact 对于联系页面

myl*_*myl 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>
Run Code Online (Sandbox Code Playgroud)

并包含在controllers.js中:

function HeaderController($scope, $location) 
{ 
    $scope.isActive = function (viewLocation) { 
        return viewLocation === $location.path();
    };
}
Run Code Online (Sandbox Code Playgroud)

  • 我建议使用`return $ location.path().indexOf(viewLocation)== 0;`而不是你可以用参数捕获页面 (40认同)
  • 由于我是新手,所以如果你能提供一个关于如何将它放入头指令的例子,我将不胜感激. (10认同)
  • @SvenHecht对该逻辑的关注是主页链接(/)将匹配所有其他路径. (10认同)
  • 这可以完成工作,但它很难"优雅" - 在`isActive('/ dogs')的调用中必须重复路由名称,例如`/ dogs`. (7认同)
  • 如果您使用的是UI路由器,则可以使用`ui-sref-active/ui-sref-active-eq`指令,即.`ui-sref-active-eq ='active'`或`ui-sref-active ='active'`以达到相同的效果 (7认同)
  • @myl很棒的答案,但我只是想知道,是什么触发isActive()重新评估?是控制器订阅了位置的变化,还是点击了重新评估的ng-click元素? (3认同)

dav*_*ave 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>
Run Code Online (Sandbox Code Playgroud)

使用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');   
                };
            });     
        });
    }
}
}]);
Run Code Online (Sandbox Code Playgroud)


Oli*_*ier 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');
          }

        });
      });
    }
  };
});
Run Code Online (Sandbox Code Playgroud)

要使用此指令:

  1. http://mgcrea.github.io/angular-strap/下载AngularStrap

  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>


End*_*050 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>
Run Code Online (Sandbox Code Playgroud)

在AngularJS控制器中:

$scope.isActive = function (viewLocation) {
     var active = (viewLocation === $location.path());
     return active;
};
Run Code Online (Sandbox Code Playgroud)

  • 好方法.我修改了一点 - 使用了ng-class指令(ng-class = {active:isActive('/ View1')})并更新了isActive函数以返回true/false而不是类名本身. (2认同)

DVa*_*rga 12

如果您正在使用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>
Run Code Online (Sandbox Code Playgroud)

  • 注意:如果你使用`/`作为你的主页,`routerLinkActive`将认为对于以`/`开头的任何URL都是活动的,例如`/ foo /`,`/ foo/bar`等.为了完全匹配,你需要`routerLinkActive ="active"[routerLinkActiveOptions] ="{exact:true}"`. (3认同)
  • 我认为这应该是公认的答案(对于角度2+至少),为什么实现某些东西已经实现了?但是对于Bootstrap 3.3,`active`类应该在`<li>`(你可以把routerLinkActive放在routerLink或其父代) (2认同)

Mar*_*p51 8

首先,这个问题可以通过很多方式解决.这种方式可能不是最优雅的,但它确实有效.

这是一个简单的解决方案,您应该可以添加到任何项目.您可以在配置可用于关闭的路由时添加"pageKey"或其他属性.此外,您可以在$ route对象的$ routeChangeSuccess方法上实现一个侦听器,以侦听路由更改的成功完成.

当您的处理程序触发时,您获取页面键,并使用该键来查找此页面需要"ACTIVE"的元素,并应用ACTIVE类.

请记住,您需要一种方法使所有元素"处于活动状态".正如你所看到我在我的导航项目上使用.pageKey类将它们全部关闭,我正在使用.pageKey_ {PAGEKEY}来单独打开它们.将它们全部切换为非活动状态将被视为一种天真的方法,可能通过使用先前的路由仅使活动项处于非活动状态来获得更好的性能,或者您可以将jquery选择器更改为仅选择要使其处于非活动状态的活动项.使用jquery选择所有活动项可能是最好的解决方案,因为它可以确保在前一个路径上可能存在任何css错误的情况下清除当前路由的所有内容.

这意味着改变这行代码:

$(".pagekey").toggleClass("active", false);
Run Code Online (Sandbox Code Playgroud)

对这一个

$(".active").toggleClass("active", false);
Run Code Online (Sandbox Code Playgroud)

以下是一些示例代码:

给出一个bootstrap导航栏

<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>
Run Code Online (Sandbox Code Playgroud)

和角度模块和控制器如下:

<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>
Run Code Online (Sandbox Code Playgroud)

  • 这可能有效,但是反对Angular.js应用程序的一般建议:在Angular中你应该避免使用jQuery搞乱DOM; 如果你必须触摸DOM,写一个指令. (16认同)

Lès*_*sté 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>
Run Code Online (Sandbox Code Playgroud)

要么:

标题控制器

/**
 * 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.'
      }
    ];
  });
Run Code Online (Sandbox Code Playgroud)

索引页面

<!-- 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>
Run Code Online (Sandbox Code Playgroud)

如果您正在使用ui-utils,您可能也对ui-router感兴趣以管理部分/嵌套视图.


Tom*_*ear 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');
            });
        }
    };
});
Run Code Online (Sandbox Code Playgroud)

用法:

<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>
Run Code Online (Sandbox Code Playgroud)


Qwe*_*aqS 5

我使用带有$ location的ng-class指令来实现它.

<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>
Run Code Online (Sandbox Code Playgroud)

它要求导航栏位于主控制器内,可以访问$ location服务,如下所示:

bajasApp.controller('MenuCntl', ['$scope','$route', '$routeParams', '$location', 
   function MenuCntl($scope, $route, $routeParams, $location) {
   $scope.$route = $route;
   $scope.$location = $location;
   $scope.$routeParams = $routeParams;
}]);
Run Code Online (Sandbox Code Playgroud)