0

我想将 css 类设置为列表项,具体取决于子元素是否匹配某个标准。结构类似于以下示例:

<ul ng-controller="Navigation">
    <li><a href="#">Category A</a>
        <ul>
            <li><a href="a1.html">a1</a></li>
            <li><a href="a2.html">a2</a></li>
        </ul>
    </li>
    <li><a href="#">Category B</a>
        <ul>
            <li><a href="b1.html">b1</a></li>
            <li><a href="b2.html">b2</a></li>
        </ul>
    </li>
    <li><a href="contact.html">contact</a></li>
</ul>

我的模型是当前页面,比如说a2.html。如果链接具有与href模型值相同的属性,则它应该具有特定的 css 类 ( active)。这可以用这个表达式来完成:

<a href="a1.html" ng-class="{'active': currentPage == 'a1.html'}>

但这有点不雅,因为我必须重复文件名(a1.html)。是否可以将当前元素传递给函数?像这样的东西:ng-class="getClass(currentElement)"

下一个问题是,我想根据孩子是否有班级来选择父元素active。如果<a href="a1.html">a1</a>在我上面的例子中被选中,那么Category A也应该得到这个类active

结论

'stewie 的解决方案有效,但我得出的结论是 Angular 不是这项工作的最佳工具。它不是一个网络“应用程序”(Angular 的领域),而是静态 html,应该稍微丰富一下。

这个简单的 jQuery 片段可以完成这项工作:

var activeLink = $("a").filter(function() {
  return $(this).attr("href") == currentPage();
});
activeLink.addClass("active");
activeLink.parents("li").children("a").addClass("active");
4

2 回答 2

5

这可以通过在您的 UL 元素上使用自定义指令来完成,该指令将在模型更改时遍历列表并在匹配项上设置适当的“活动”类。以这个Plunker 为例。请注意,该指令可以进一步优化。这只是一个演示。

HTML:

<ul menu ng-controller="Navigation">
  <li><a href="#">Category A</a>
    <ul>
      <li><a href="a1.html">a1</a></li>
      <li><a href="a2.html">a2</a></li>
    </ul>
  </li>
  <li><a href="#">Category B</a>
    <ul>
      <li><a href="b1.html">b1</a></li>
      <li><a href="b2.html">b2</a></li>
    </ul>
  </li>
  <li><a href="contact.html">contact</a></li>
</ul>

JS:

var app = angular.module('plunker', []);
app.controller('Navigation', 
    function($scope) {}
  );

app.directive('menu',
  function(){
    return {
      link: function ($scope, $element) {
        var link, li;
        $scope.$watch('currentPage', function(page){
          activate(page);
        });

        function activate(page){
          angular.forEach($element.find('li'), function(elm){
            li = angular.element(elm);
            link = li.find('a');
            if(link.attr('href') === $scope.currentPage){
              li.addClass('active');
              li.parents('li').addClass('active');
              return;
            }
            li.removeClass('active');
          });
        }
      }
    };
  }
);
于 2013-02-26T22:21:43.457 回答
0

我看了一下@Stewei 的解决方案。但是为此使用指令编写解决方案对我来说没有意义。我认为这些指令仅在您创建组件或删除模板时编写。即使是为了消除模板,我也建议人们使用 ng-include 或类似的东西,除非您想要自定义元素提供的语义。

但是,我相信 Angular 的做法是将行为逻辑与“应用程序特定”逻辑完全分开。我认为你编写指令的方式是它们独立于它周围的控制器。

这是一个实际上解决了这个问题的 plunkr,希望以最“有角度的方式”成为可能。如果您可以对所有链接使用某种数据模型并且可能在该模型上重复重复,则可以进一步解耦。但这是开发商的选择。既然你提到它是一个静态页面,这个解决方案可能最适合它。

http://plnkr.co/edit/DjaYi1ofpFKgKfhtakub?p=preview

在您最初的问题中,您确实问过是否可以将 currentElement 传递给 getClass 方法。我以前问过这个问题,答案是否定的。唯一可以传递对 currentElement 的引用的地方是指令控制器,但目前不在主题范围内。

这是完成手头任务的代码。

HTML:

<div ng-controller="NavController">
  <ul >
    <li ng-class="getCategoryClass('A')">
        <a href="#">Category A</a>
        <ul>
            <li ng-class="getClass('a1.html','A')"><a href="a1.html">a1</a></li>
            <li ng-class="getClass('a2.html','A')"><a href="a2.html">a2</a></li>
        </ul>
    </li>
    <li ng-class="getCategoryClass('B')">
      <a href="#">Category B</a>
        <ul>
            <li ng-class="getClass('b1.html','B')"><a href="b1.html">b1</a></li>
            <li ng-class="getClass('b2.html','B')"><a href="b2.html">b2</a></li>
        </ul>
    </li>
    <li ng-class="getClass('contact.html','contact')"><a href="contact.html">contact</a></li>
  </ul>

  <input ng-model="currentPage" />
  <br>
  currentPage: {{currentPage}}
</div>

JS:

app.controller('NavController', 
    function($scope) {
      $scope.currentPage = "";
      $scope.currentCategory = "";
      $scope.pageActive = false;
      $scope.getClass = function(page,category){

        if( page === $scope.currentPage ) {
          $scope.pageActive = true;
          $scope.currentCategory = category;
          return "active";
        }
        else{
          return "";
        }
      };

      $scope.$watch('currentPage',function(val){
        $scope.pageActive = false;
      });

      $scope.onLinkClick = function($event){
        $event.preventDefault();  
      };

      $scope.getCategoryClass = function(category){
        return $scope.currentCategory === category && $scope.pageActive ? "active" : "";
      };
    }
  );
于 2013-03-24T15:38:49.603 回答