【问题标题】:AngularJS, Two level menu add "active" class to both the active sub-item and its parent based on urlAngularJS,两级菜单根据url向活动子项及其父项添加“活动”类
【发布时间】:2013-10-22 13:56:45
【问题描述】:

如果只是一级导航/菜单,则 url 如“localhost/#/user”

我知道我可以使用

<ul>
  <li ng-class="{active: isActive('/user')}><a href="#/user'>User</a></li>
</ul>

在控制器中

$scope.isActive = function (path) {
  if ( path == $location.path() )
    return true;
  return false;
};

那么当url为“localhost/#/user”时,将添加“active”。

然而,当涉及到两级菜单,像“localhost/#/user/orders”这样的url

<ul>
  <li>
    <a href="#/user'>User</a>
    <ul>
      <li><a href="#/user/orders'>Orders</a></li>
    </ul>
  </li>   
</ul>

如何根据 url 向项目“订单”及其父“用户”添加“活动”类?(这样我可以同时突出显示它们)

提前致谢。


更新:

谢谢,现在可以用了:D

@Nikos Paraskevopoulos、@piatek、@Chandermani 谢谢

这是我用 CoffeeScript 编写的最终工作代码,虽然代码不够好,但它可以工作:)

.directive('highlightActive', () ->
    return {
        restrict: "A"
        controller: [
            '$scope', '$element', '$attrs', '$location'
            ($scope, $element, $attrs, $location) ->
                links = $element.find('a')
                path = () ->
                    return $location.path()

                highlightActive = (links, path) ->
                    path = '#' + path

                    angular.forEach(links, (link) ->
                        $link = angular.element(link)
                        $li = $link.parent('li')
                        href = $link.attr('href')

                        if ($li.hasClass('active'))
                            $li.removeClass('active')
                        if path.indexOf(href) is 0
                            $li.addClass('active')
                    )

                highlightActive(links, $location.path())

                $scope.$watch(path, (newVal, oldVal) ->
                    if newVal is oldVal
                        return
                    highlightActive(links, $location.path())
                )
        ]

    }
)

【问题讨论】:

    标签: javascript css angularjs


    【解决方案1】:

    如果您的 URL 遵循菜单的层次结构(即 /user/user/orders/user/orders/something,其中 → 表示子菜单),您可以使用简单的指令检查字符串包含情况:

    app.directive("menuHref", function() {
        return {
            restrict: "A",
            template: "<li><a ng-href='{{ href }}'>{{ text }}</a></li>",
            scope: {
                text: "="
            },
            controller: ["$scope", "$element", "$attrs", "$location", function($scope, $element, $attrs, $location) {
                $scope.href = "#" + $attrs.menuHref;
    
                $scope.$watch(
                    function() {
                        return $location.hash().startsWith($attrs.menuHref);
                    },
                    function(newval) {
                        $element.toggleClass("active", newval);
                    }
                );
            }]
        };
    });
    

    将其用作:

    <li menu-href="/user/orders" text="Orders"></li>
    

    (注意href不以#开头,&lt;a&gt;是指令生成的)

    我没有测试过这段代码,它可能包含小错误(我们可以讨论它们),但我认为这个原理应该有效。

    【讨论】:

    • 很好,但为什么要在控制器中设置 $watch 而不是在链接函数中?有什么好处?
    • @piatek 我需要访问$location 服务,因此我需要控制器,因为它可以指定依赖项。所以我把整个逻辑都放在了控制器里面,这样就可以放在一个地方了。
    【解决方案2】:

    我能想到的一种方法是将多个参数传递给isActive,例如

    <li ng-class="{active: isActive(['/user','/user/orders'])}><a href="#/user'>User</a></li>
    

    然后检查是否匹配任一路径。

    【讨论】:

    • 谢谢 :) 它应该可以工作,但是如果一个列表有很多子列表,比如 6 个,那么数组会很长 :P
    • 同意,我明白这一点。如果我能想到别的,我会更新答案:)
    【解决方案3】:

    有很多方法可以做到这一点,我只想在顶部元素上添加一个指令,因为 Angular 无论如何都会增强 HTML。

    <ul activeli>
      <li>
        <a href="#/users">User</a>
        <ul>
          <li>
            <a href="#/users/orders/">Orders</a>
          </li>
          <li>
            <a href="#/users/account/">Account</a>
          </li>
        </ul>
      </li>
    </ul>
    
    App.directive('activeli', function ($location) {
      return function ($scope, $el) {
        var links = $el.find('a'),
            path = function(){ return $location.path(); }
    
        function addActiveClass (links, path) {
            angular.forEach(links, function (link) {
                var $link = angular.element(link);
    
                if ($link.hasClass('active')) {
                    $link.removeClass('active');
                } else if (link.hash === ('#' + path)) {
                    $link.addClass('active');
                }
            });
        }
    
        // Initial state
        addActiveClass(links, $location.path());
    
        $scope.$watch(path, function (newValue, oldValue) {
            if (newValue === oldValue) return;
            addActiveClass(links, $location.path());
        });
      };
    
    });
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-12-20
      • 2019-03-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-08-05
      • 2019-03-20
      • 1970-01-01
      相关资源
      最近更新 更多