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 はこの仕事に最適なツールではないという結論に達しました。これは Web 'アプリケーション' (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要素でカスタムディレクティブを使用して実行できます。このディレクティブは、モデルが変更されるたびにリストをトラバースし、一致するアイテムに適切な「アクティブ」クラスを設定します。例としてこのプランカーを参照してください。ディレクティブはさらに最適化できることに注意してください。これは単なるデモンストレーションです。

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 です。すべてのリンクに対してある種のデータモデルを使用でき、そのモデルで ng-repeat を実行できる場合、これをさらに分離できます。しかし、それは開発者次第です。静的ページだとおっしゃっていたので、この解決策がおそらく最適です。

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

元の質問では、 currentElement を getClass メソッドに渡すことができるかどうか尋ねました。以前にも質問したことがありますが、答えは NO です。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 に答える