AngularJS,两级菜单根据url为活动子项及其父级添加“活动”类

时间:2013-10-21 08:58:45

标签: javascript css angularjs

如果它只是一个级别的导航/菜单,网址就像“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”

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

如何根据网址将“有效”类添加到项目“订单”及其父“用户”?(所以我可以突出显示它们)

提前致谢。


更新

谢谢,它现在正在工作: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())
                )
        ]

    }
)

3 个答案:

答案 0 :(得分:2)

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

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

然后检查匹配任何一条路径。

答案 1 :(得分:2)

如果您的网址遵循菜单的层次结构(即/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不以#开头,<a>由指令生成

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

答案 2 :(得分:1)

有很多方法可以做到这一点,我只想在顶部元素上添加一个指令,因为角度倾向于加强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());
    });
  };

});