web-dev-qa-db-ja.com

angular-uiのアコーディオンをプログラムで制御する良い方法は何ですか?

http://angular-ui.github.com/bootstrap/ のアコーディオンディレクティブを使用しており、アコーディオンの開閉をより詳細に制御する必要があります。

より正確には、親アコーディオンを閉じて次のアコーディオンを開くアコーディオングループ内のボタンが必要です(したがって、基本的には、close-othersがtrueに設定されている場合に次のヘッダーをクリックするとどうなるかを模倣します)。また、アコーディオンを閉じて次のアコーディオンを開くことができるようにする前に、いくつかの検証を行う必要があります。また、これをアコーディオンヘッダーのクリックイベントに接続する必要があります。

私はangularにかなり慣れており、現在、アプリケーションをBackbone + JQueryからAngularに書き換えています。Backbone-versionでは、Twitter Bootstrap accordionsそして、私たちはJQueryを使用してそれらを開閉していました。これを引き続き行うことはできますが、JQuery DOM操作を完全に取り除くので、純粋なangular解決策を探しています。

検証に関して私がやろうとしたのは

<accordion-group ng-click="close($event)">

そして私のコントローラーで

    event.preventDefault();
    event.stopPropagation();

DOM要素がディレクティブに置き換えられ、クリックハンドラーが追加されることはないため、これは明らかに機能しませんでした。私はソースコードを調べてきました(そしていくつかの非常に素晴らしい文書化されていない機能を見つけました)が、この特定の課題の解決をどこから始めればよいのか途方に暮れています。 angular-uiをフォークすることを検討していて、この機能をアコーディオンディレクティブに追加しようとしましたが、ディレクティブを変更せずにこれを実現できれば、はるかに優れています。

16
ivarni

そこには is-open属性のaccordion-groupはバインド可能な式を指します。この式を使用すると、アコーディオンアイテムをプログラムで制御できます。例:

<div ng-controller="AccordionDemoCtrl">
  <accordion>
    <accordion-group ng-repeat="group in groups" heading="{{group.title}}" is-open="group.open">
      {{group.content}}
    </accordion-group>    
  </accordion>
  <button class="btn" ng-click="groups[0].open = !groups[0].open">Toggle first open</button>
  <button class="btn" ng-click="groups[1].open = !groups[1].open">Toggle second open</button>
</div>

そしてここに働くplunk: http://plnkr.co/edit/DepnVH?p=preview

25

@ pkozlowski.opensourceによるソリューションが機能しない場合(たとえば私)は、コンポーネントに強制的にCSSを受け入れるようにして(遷移なしで)コンポーネントを閉じることができます。

Theory: angularディレクティブは、主にCSSスタイルがアコーディオンの外観を与える標準のdiv要素に展開されます。クラス_.panel-collapse_はaccordion-group要素の本体です。以下のように、2番目のクラスを_.in_から_.collapse_に変更し、他のいくつかの変更を加えることができます。

コード:

_$scope.toggleOpen = function(project) {

        var id = '<The ID of the accordion-group you want to close>';
        var elements = angular.element($document[0].querySelector('#'+id));
        var children = elements.children();

        for(var i = 0; i < children.length; i++) {

            var child = angular.element(children[i]);

            if(child.hasClass('panel-collapse')) {
                if(child.hasClass('in')) { // it is open
                    child.removeClass('in');
                    child.addClass('collapse');
                    child.css('height', '0px');
                } else { // it is closed
                    child.addClass('in');
                    child.removeClass('collapse');
                    child.css('height', 'auto');
                }

            }
        }
    };
_

Angularについて説明しているように、ng-repeatタグを介してアコーディオンを生成している可能性は十分にあります。この場合、次のような要素のIDを生成することもできます。

_<accordion-group ng-repeat="user in users"
                 is-disabled="user.projects.length == 0"
                 id="USER{{user._id}}">
_

Mongooseモデルのユーザーの場合、指定するIDは_user._id_ではなく、先頭に「USER」が追加されていることに注意してください。これは、Mongooseが数値で始まるIDを生成する可能性があり、querySelectorがそれを好まないためです。

5
Mike M