web-dev-qa-db-ja.com

AngularJs:ビューが完全にレンダリングされた後にディレクティブを実行する

私はすべてのAngular Worldに不慣れです。ディレクティブを管理する問題に直面しています。

タブを使用するプロジェクトで作業しています。ウィンドウサイズがすべてのタブの幅よりも狭い場合、オーバーフローしたタブを処理するように機能を拡張したいので、これを実現するために要素のいくつかの寸法を計算する必要があります。タブは$ scopeのオブジェクトから作成されます。問題は、ビューが完全にコンパイルされる前に、寸法を計算するディレクティブが実行されることです。

Plnkrリンク:http://plnkr.co/edit/LOT4sZsNxnfmQ8zHymvw?p=preview

私が試したこと:

  1. templateUrlを使用してディレクティブにテンプレートを読み込む
  2. トランスクルードの操作
  3. ng-repeatで$ lastを使用するには
  4. ディレクティブを並べ替えて、すべてのタブにダミーディレクティブを作成し、イベントをトリガーします

AngularJsイベント、またはこの状況を処理するプロパティがあると思います。

みんな助けてください:)

20
Abu Qusai

私はあなたのプランカーに枝を作ります、私はこれがあなたが探していたものだと思います

ディレクティブをこれに変更します

.directive('onFinishRenderFilters', function ($timeout) {
    return {
        restrict: 'A',
        link: function (scope, element, attr) {
            if (scope.$last === true) {
                $timeout(function () {
                    scope.$emit('ngRepeatFinished');
                });
            }
        }
    }
});

次に、HTMLにディレクティブを追加しました

 <li ng-repeat="tab in tabs" on-finish-render-filters>

そして、繰り返し終了した後に実行したいコードを最後に配置しました

$scope.$on('ngRepeatFinished', function (ngRepeatFinished) {
        $scope.tabs = [{
            index: 1,
            title: "Tab 1",
            link: "/tab1/"
        },{
            index: 2,
            title: "Tab 2",
            link: "/tab2/"
        },{
            index: 3,
            title: "Tab 3",
            link: "/tab3/"
        },{
            index: 4,
            title: "Tab 4",
            link: "/tab4/"
        }];

  });

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

8
agusgambina

AngularJSには、ng-repeat内で使用されるディレクティブに対する信頼できるポストレンダーコールバックがないようです。 [1]

たぶん、特定の画面幅に対応するオーバーフロー制御要素を追加することで、CSSレベルでこれを解決できます。

  1. https://groups.google.com/forum/#!topic/angular/SCc45uVhTt8

更新:ネストされた$ timeoutsを使用してこれを行う方法があります。参照: http://lorenzmerdian.blogspot.de/2013/03/how-to-handle-dom-updates-in-angularjs.html

6
Gregor

実際のDOM要素にウォッチを追加して、ng-repeatがいつDOMにロードされるかを知ることができます。

UlにIDを付けます(#tabsなど)

$scope.$watch(
    function () { return document.getElementById('tabs').innerHTML },  
    function(newval, oldval){
        //console.log(newval, oldval);
        //do what you like
    }, true);

あなたのコメントによると、あなたはすでにうまくいく解決策を持っています...そしてそれが現在私が知っている唯一の解決策です:$ timeout。

問題は、何を達成したいですか?すべてのレンダリングが完了したときにコールバックが必要です。わかりましたが、どうすればangularこれを知ることができますか?Angularを使用しているときに開発している最新のアプリでは、再レンダリングが常に発生する可能性があります!データが読み込まれる場所でjsイベントが発生する可能性がありますアプリを初期化した直後でもバックエンド。再レンダリングが発生します。ユーザーによるマウスの移動により、CSSルールにより角度スコープの範囲外にある要素の再レンダリングがトリガーされる可能性があります。いつでも再レンダリングが発生する可能性があります。

では、これらの考慮事項を踏まえて、angularJSがレンダリングの完了時に何を通知できるのでしょうか。現在の$ applyおよび/または$ digestチェーンが処理されるとき、つまりブラウザーのイベントキューが今のところ空であることがわかるだけです。まさにそれがangularJSが知っている唯一の情報です。そして、これには遅延0の$ timeoutを使用します。

はい、あなたは正しいです、より大きなアプリケーションでは、それはもはや信頼できなくなる点までトリッキーになる可能性があります。しかし、この場合は、これを別の方法で解決する方法を考える必要があります。 F.i.再レンダリングが後で発生する場合は、バックエンドからロードされる新しいデータなどの原因が必要です。もしそうなら、あなたはデータがいつ読み込まれるかを知っているので再レンダリングが起こり、それゆえあなたが幅を更新しなければならないときを正確に知っています。

3
Marco Rinck