Javascript 使用AngularJS设置活动选项卡样式

Javascript 使用AngularJS设置活动选项卡样式,javascript,html,angularjs,Javascript,Html,Angularjs,我在AngularJS中设置了如下路线: $routeProvider .when('/dashboard', {templateUrl:'partials/dashboard', controller:widgetsController}) .when('/lab', {templateUrl:'partials/lab', controller:widgetsController}) myApp.controller('MyCtrl', function($scope, $

我在AngularJS中设置了如下路线:

$routeProvider
    .when('/dashboard', {templateUrl:'partials/dashboard', controller:widgetsController})
    .when('/lab', {templateUrl:'partials/lab', controller:widgetsController})
myApp.controller('MyCtrl', function($scope, $location) {
    $scope.isActive = function(route) {
        return route === $location.path();
    }
});
<nav id="header_tabs" find-active-tab="1">
    <a href="#/home" class="nav_tab">HOME</a>
    <a href="#/finance" class="nav_tab">Finance</a>
    <a href="#/hr" class="nav_tab">Human Resources</a>
    <a href="#/quarterly" class="nav_tab">Quarterly</a>
</nav>
# Directive
angular.module('myapp.directives')
.directive 'ActiveTab', ($route) ->
  restrict: 'A'

  link: (scope, element, attrs) ->
    klass = "active"

    if $route.current.activeTab? and attrs.flActiveLink is $route.current.activeTab
      element.addClass(klass)

    scope.$on '$routeChangeSuccess', (event, current) ->
      if current.activeTab? and attrs.flActiveLink is current.activeTab
        element.addClass(klass)
      else
        element.removeClass(klass)

# Routing
$routeProvider
.when "/page",
  templateUrl: "page.html"
  activeTab: "page"
.when "/other_page",
  templateUrl: "other_page.html"
  controller: "OtherPageCtrl"
  activeTab: "other_page"

# View (.jade)
a(ng-href='/page', active-tab='page') Page
a(ng-href='/other_page', active-tab='other_page') Other page
    <ul class="nav navbar-nav">
        <li class-on-active-link="active"><a href="/orders">Orders</a></li>
        <li class-on-active-link="active"><a href="/distributors">Distributors</a></li>
    </ul>

我在顶栏上有一些标签样式的链接。如何根据当前模板或url向选项卡添加“活动”类?

一种方法是使用ngClass指令和$location服务。在模板中,您可以执行以下操作:

ng-class="{active:isActive('/dashboard')}"
其中,
isActive
将是定义如下的范围内的函数:

$routeProvider
    .when('/dashboard', {templateUrl:'partials/dashboard', controller:widgetsController})
    .when('/lab', {templateUrl:'partials/lab', controller:widgetsController})
myApp.controller('MyCtrl', function($scope, $location) {
    $scope.isActive = function(route) {
        return route === $location.path();
    }
});
<nav id="header_tabs" find-active-tab="1">
    <a href="#/home" class="nav_tab">HOME</a>
    <a href="#/finance" class="nav_tab">Finance</a>
    <a href="#/hr" class="nav_tab">Human Resources</a>
    <a href="#/quarterly" class="nav_tab">Quarterly</a>
</nav>
# Directive
angular.module('myapp.directives')
.directive 'ActiveTab', ($route) ->
  restrict: 'A'

  link: (scope, element, attrs) ->
    klass = "active"

    if $route.current.activeTab? and attrs.flActiveLink is $route.current.activeTab
      element.addClass(klass)

    scope.$on '$routeChangeSuccess', (event, current) ->
      if current.activeTab? and attrs.flActiveLink is current.activeTab
        element.addClass(klass)
      else
        element.removeClass(klass)

# Routing
$routeProvider
.when "/page",
  templateUrl: "page.html"
  activeTab: "page"
.when "/other_page",
  templateUrl: "other_page.html"
  controller: "OtherPageCtrl"
  activeTab: "other_page"

# View (.jade)
a(ng-href='/page', active-tab='page') Page
a(ng-href='/other_page', active-tab='other_page') Other page
    <ul class="nav navbar-nav">
        <li class-on-active-link="active"><a href="/orders">Orders</a></li>
        <li class-on-active-link="active"><a href="/distributors">Distributors</a></li>
    </ul>
以下是完整的JSFIDLE:


在每个导航选项卡上重复
ng class=“{active:isActive('/dashboard')}”
可能会很乏味(如果您有许多选项卡)因此,这个逻辑可能是一个非常简单的指令的候选者。

解决这个问题而不必依赖URL的方法是在
$routeProvider
配置期间为每个部分添加一个自定义属性,如下所示:

$routeProvider.
    when('/dashboard', {
        templateUrl: 'partials/dashboard.html',
        controller: widgetsController,
        activetab: 'dashboard'
    }).
    when('/lab', {
        templateUrl: 'partials/lab.html',
        controller: widgetsController,
        activetab: 'lab'
    });
在控制器中公开
$route

function widgetsController($scope, $route) {
    $scope.$route = $route;
}
根据当前活动选项卡设置
活动
类:

<li ng-class="{active: $route.current.activetab == 'dashboard'}"></li>
<li ng-class="{active: $route.current.activetab == 'lab'}"></li>

  • 像这样的指令可能会解决您的问题:

    HTML

    您也可以简单地使用它来推断导航的样式:

    function IndexController( $scope, $rootScope, $location ) {
      $rootScope.location = $location;
      ...
    }
    
    然后在您的
    ng类中使用它:

    <li ng-class="{active: location.path() == '/search'}">
      <a href="/search">Search><a/>
    </li>
    
  • 搜索>

  • 我同意Rob关于在控制器中具有自定义属性的帖子。显然我没有足够的代表评论。以下是请求的JSFIDLE:

    示例html

    <div ng-controller="MyCtrl">
        <ul>
            <li ng-repeat="link in links" ng-class="{active: $route.current.activeNav == link.type}"> <a href="{{link.uri}}">{{link.name}}</a>
    
            </li>
        </ul>
    </div>
    

    @rob juurlink我对您的解决方案做了一些改进:

    而不是每条路线都需要一个活动选项卡;需要在每个控制器中设置活动选项卡,我可以执行以下操作:

    var App = angular.module('App',[]);
    App.config(['$routeProvider', function($routeProvider){
      $routeProvider.
      when('/dashboard', {
        templateUrl: 'partials/dashboard.html',
        controller: Ctrl1
      }).
      when('/lab', {
        templateUrl: 'partials/lab.html',
        controller: Ctrl2
      });
    }]).run(['$rootScope', '$location', function($rootScope, $location){
       var path = function() { return $location.path();};
       $rootScope.$watch(path, function(newVal, oldVal){
         $rootScope.activetab = newVal;
       });
    }]);
    
    HTML是这样的。activetab只是与该路由相关的url。这只是消除了在每个控制器中添加代码的需要(如果这是使用它们的唯一原因,则拖动$route和$rootScope等依赖项)


    按照Pavel关于使用自定义指令的建议,这里有一个版本,它不需要向routeConfig添加有效负载,是超级声明性的,并且可以调整为对路径的任何级别作出反应,只需更改您要注意的
    切片()

    app.directive('detectActiveTab', function ($location) {
        return {
          link: function postLink(scope, element, attrs) {
            scope.$on("$routeChangeSuccess", function (event, current, previous) {
                /*  
                    Designed for full re-usability at any path, any level, by using 
                    data from attrs. Declare like this: 
                    <li class="nav_tab">
                      <a href="#/home" detect-active-tab="1">HOME</a>
                    </li> 
                */
    
                // This var grabs the tab-level off the attribute, or defaults to 1
                var pathLevel = attrs.detectActiveTab || 1,
                // This var finds what the path is at the level specified
                    pathToCheck = $location.path().split('/')[pathLevel] || 
                      "current $location.path doesn't reach this level",
                // This var finds grabs the same level of the href attribute
                    tabLink = attrs.href.split('/')[pathLevel] || 
                      "href doesn't include this level";
                // Above, we use the logical 'or' operator to provide a default value
                // in cases where 'undefined' would otherwise be returned.
                // This prevents cases where undefined===undefined, 
                // possibly causing multiple tabs to be 'active'.
    
                // now compare the two:
                if (pathToCheck === tabLink) {
                  element.addClass("active");
                }
                else {
                  element.removeClass("active");
                }
            });
          }
        };
      });
    
    因此,如果选项卡应该对路径的基本级别作出反应,则将参数设为“1”。因此,当location.path()为“/home”时,它将与
    href
    中的“#/home”匹配。如果您的选项卡应该对路径的第二级、第三级或第11级作出反应,请相应地进行调整。从1或更大的值进行切片将绕过href中的邪恶“#”,它将位于索引0处

    唯一的要求是在
    
    
    请注意,这个版本不再像引导式HTML。但是,它更现代,使用更少的元素,所以我偏爱它。这个版本的指令,加上最初的指令,现在是一个插入模块,您可以声明为依赖项。如果有人真的使用它们的话,我很乐意给它们加上颜色

    另外,若您想要一个包含
  • 的引导兼容版本,您可以使用,我认为这是在这篇原始文章之后发布的,可能比这篇文章更具声明性。对于基本内容来说,它不太简洁,但为您提供了一些附加选项,如禁用的选项卡和在激活和停用时触发的声明性事件。

    我建议使用,它不仅支持多视图和嵌套视图,而且使这类工作非常简单(下面引用的代码):


    值得一读。

    我发现XMLilley的anwser是最好的、适应性最强的、非侵入性的

    然而,我有一个小故障

    为了与引导nav一起使用,我对其进行了如下修改:

    app.directive('activeTab', function ($location) {
        return {
          link: function postLink(scope, element, attrs) {
            scope.$on("$routeChangeSuccess", function (event, current, previous) {
                /*  designed for full re-usability at any path, any level, by using 
                    data from attrs
                    declare like this: <li class="nav_tab"><a href="#/home" 
                                       active-tab="1">HOME</a></li> 
                */
                if(attrs.href!=undefined){// this directive is called twice for some reason
                    // this var grabs the tab-level off the attribute, or defaults to 1
                    var pathLevel = attrs.activeTab || 1,
                    // this var finds what the path is at the level specified
                        pathToCheck = $location.path().split('/')[pathLevel],
                    // this var finds grabs the same level of the href attribute
                        tabLink = attrs.href.split('/')[pathLevel];
                    // now compare the two:
                    if (pathToCheck === tabLink) {
                      element.parent().addClass("active");//parent to get the <li>
                    }
                    else {
                      element.parent().removeClass("active");
                    }
                }
            });
          }
        };
      });
    
    app.directive('activeTab',函数($location){
    返回{
    链接:函数postLink(范围、元素、属性){
    作用域:$on(“$routeChangeSuccess”),函数(事件、当前、以前){
    /*通过使用
    来自ATTR的数据
    这样声明:
  • */ 如果(attrs.href!=undefined){//出于某种原因,此指令被调用两次 //该变量获取属性的选项卡级别,或默认为1 var pathLevel=attrs.activeTab | | 1, //此变量查找指定级别的路径 pathToCheck=$location.path().split('/')[pathLevel], //此var finds获取相同级别的href属性 tabLink=attrs.href.split('/')[pathLevel]; //现在比较两个: 如果(pathToCheck==tabLink){ element.parent().addClass(“active”);//获取
  • } 否则{ element.parent().removeClass(“活动”); } } }); } }; });
  • 我添加了“if(attrs.href!=undefined)”,因为这个函数被调用了两次,第二次产生错误

    至于html:

    <ul class="nav nav-tabs">
       <li class="active" active-tab="1"><a href="#/accueil" active-tab="1">Accueil</a></li>
       <li><a active-tab="1" href="#/news">News</a></li>
       <li><a active-tab="1" href="#/photos" >Photos</a></li>
       <li><a active-tab="1" href="#/contact">Contact</a></li>
    </ul>
    

    这是XMLillies的另一个版本,它使用了搜索字符串而不是路径级别。我认为这对于我的用例来说更为明显

    statsApp.directive('activeTab', function ($location) {
      return {
        link: function postLink(scope, element, attrs) {
          scope.$on("$routeChangeSuccess", function (event, current, previous) {
            if (attrs.href!=undefined) { // this directive is called twice for some reason
              // The activeTab attribute should contain a path search string to match on.
              // I.e. <li><a href="#/nested/section1/partial" activeTab="/section1">First Partial</a></li>
              if ($location.path().indexOf(attrs.activeTab) >= 0) {
                element.parent().addClass("active");//parent to get the <li>
              } else {
                element.parent().removeClass("active");
              }
            }
          });
        }
      };
    });
    
    statsApp.directive('activeTab',function($location){
    返回{
    链接:函数postLink(范围、元素、属性){
    
    # Directive
    angular.module('myapp.directives')
    .directive 'ActiveTab', ($route) ->
      restrict: 'A'
    
      link: (scope, element, attrs) ->
        klass = "active"
    
        if $route.current.activeTab? and attrs.flActiveLink is $route.current.activeTab
          element.addClass(klass)
    
        scope.$on '$routeChangeSuccess', (event, current) ->
          if current.activeTab? and attrs.flActiveLink is current.activeTab
            element.addClass(klass)
          else
            element.removeClass(klass)
    
    # Routing
    $routeProvider
    .when "/page",
      templateUrl: "page.html"
      activeTab: "page"
    .when "/other_page",
      templateUrl: "other_page.html"
      controller: "OtherPageCtrl"
      activeTab: "other_page"
    
    # View (.jade)
    a(ng-href='/page', active-tab='page') Page
    a(ng-href='/other_page', active-tab='other_page') Other page
    
    <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>
    
    function HeaderController($scope, $location) 
    { 
        $scope.isActive = function (viewLocation) { 
            return viewLocation === $location.path();
        };
    }
    
    angular.module('myApp').directive('classOnActiveLink', [function() {
        return {
            link: function(scope, element, attrs) {
    
                var anchorLink = element.children()[0].getAttribute('ng-href') || element.children()[0].getAttribute('href');
                anchorLink = anchorLink.replace(/^#/, '');
    
                scope.$on("$routeChangeSuccess", function (event, current) {
                    if (current.$$route.originalPath == anchorLink) {
                        element.addClass(attrs.classOnActiveLink);
                    }
                    else {
                        element.removeClass(attrs.classOnActiveLink);
                    }
                });
    
            }
        };
    }]);
    
        <ul class="nav navbar-nav">
            <li class-on-active-link="active"><a href="/orders">Orders</a></li>
            <li class-on-active-link="active"><a href="/distributors">Distributors</a></li>
        </ul>
    
    'use strict';
    
    angular.module('cloudApp')
      .controller('MenuController', function ($scope, $location, CloudAuth) {
        $scope.menu = [
          {
            'title': 'Dashboard',
            'iconClass': 'fa fa-dashboard',
            'link': '/dashboard',
            'active': true
          },
          {
            'title': 'Devices',
            'iconClass': 'fa fa-star',
            'link': '/devices'
          },
          {
            'title': 'Settings',
            'iconClass': 'fa fa-gears',
            'link': '/settings'
          }
        ];
        $location.path('/dashboard');
        $scope.isLoggedIn = CloudAuth.isLoggedIn;
        $scope.isAdmin = CloudAuth.isAdmin;
        $scope.isActive = function(route) {
          return route === $location.path();
        };
      });
    
    <li role="presentation" ng-class="{active:isActive(menuItem.link)}" ng-repeat="menuItem in menu"><a href="{{menuItem.link}}"><i class="{{menuItem.iconClass}}"></i>&nbsp;&nbsp;{{menuItem.title}}</a></li>
    
    <section ng-init="tab=1">
                    <ul class="nav nav-tabs">
                        <li ng-class="{active: tab == 1}"><a ng-click="tab=1" href="#showitem">View Inventory</a></li>
                        <li ng-class="{active: tab == 2}"><a ng-click="tab=2" href="#additem">Add new item</a></li>
                        <li ng-class="{active: tab == 3}"><a ng-click="tab=3" href="#solditem">Sold item</a></li>
                    </ul>
                </section>
    
    <ul>
      <li ui-sref-active="active" class="item">
        <a href ui-sref="app.user({user: 'bilbobaggins'})">@bilbobaggins</a>
      </li>
      <!-- ... -->
    </ul>
    
    <ul>
      <li ui-sref-active="active" class="item active">
        <a ui-sref="app.user({user: 'bilbobaggins'})" href="/users/bilbobaggins">@bilbobaggins</a>
      </li>
      <!-- ... -->
    </ul>
    
    <a ui-sref="home" ui-sref-opts="{reload: true}">Home</a>
    
    <nav role="navigation">
        <ul>
            <li ui-sref-active="selected" class="inactive"><a ui-sref="tab-01">Tab 01</a></li> 
            <li ui-sref-active="selected" class="inactive"><a ui-sref="tab-02">Tab 02</a></li>
        </ul>
    </nav>
    
      .selected {
        background-color: $white;
        color: $light-blue;
        text-decoration: none;
        border-color: $light-grey;
      } 
    
    angular
      .module('appApp', [
        'ngRoute'
     ])
    config(function ($routeProvider) {
        $routeProvider
          .when('/', {
            templateUrl: 'views/main.html',
            controller: 'MainCtrl',
            controllerAs: 'main'
          })
          .when('/about', {
            templateUrl: 'views/about.html',
            controller: 'AboutCtrl',
            controllerAs: 'about'
          })
    }
    });
    
    angular
          .module('appApp', [
            'ngRoute'
         ])
        config(function ($routeProvider) {
            $routeProvider
              .when('/', {
                templateUrl: 'views/main.html',
                controller: 'MainCtrl',
                activetab: 'main'
              })
              .when('/about', {
                templateUrl: 'views/about.html',
                controller: 'AboutCtrl',
                activetab: 'about'
              })
        }
        })
      .controller('navController', function ($scope, $route) {
        $scope.$route = $route;
      });
    
    ng-class="{active: $route.current.activetab == 'about'}"