web-dev-qa-db-ja.com

ビューが変更されたときにAngularJSからJQuery関数を呼び出す方法

私はAngularJSを初めて使用し、アプリケーションに jQueryカスタムコンテンツスクローラー を実装する際に問題に対処しています。

Angularでコンテンツを更新する場合、スクローラーを更新する必要があります。このため、スクローラーにはupdateメソッドがあります。私の問題は、どこに呼べばいいのかわからないということです。コンテンツのマークアップは次のとおりです。

<div class="scroll-list Nice-scrollbars">
    <ul class="gallery clearfix">
        <li class="extra-alt" ng-repeat="item in relatedItems.data">
            ...
        </li>
    </ul>
</div>

Angularの$http.postのsuccessブランチでupdateメソッドを呼び出そうとしていました。

$scope.relatedItems = $http.post($scope.url, {
    'filterType': 'related', 'film': id
}).success(function() {
    $(".Nice-scrollbars").mCustomScrollbar('update');
});

これは機能しませんでした。successメソッドが呼び出されたときに、ビューのコンテンツがまだ更新されていないためだと思います(alert関数を使用して表示でき、ダイアログボックスを閉じた後にデータが表示されました)

スクロールバーを機能させる唯一の方法は、コンテンツの変更を監視するためにスクローラーの詳細プロパティを使用することでした(これらはスクロールバーに渡されるオプションです)。

var scrollbarOpts = {
    scrollButtons:{
        enable:true
    },
    advanced:{
        updateOnContentResize: true
        //@TODO: get rid of this, correctly find where to call update method
    }
}

このオプションはスクリプト全体のパフォーマンスを低下させるため、これは悪い習慣です。 必要に応じてDOMを更新するために必要なjQueryメソッドを呼び出す正しい場所はどこですか、またはAngularJSで変更を表示するためのそのようなバインディングはどのように正しく行われますか?

13
Teo.sk

DOM操作は、(コントローラーではなく)ディレクティブで実行する必要があります。ディレクティブは変更のためにモデルを$ watch()する必要があり、watchコールバックはjQueryDOM操作を実行する必要があります。 AngularがDOMを更新/変更した後(ただし、ブラウザーがレンダリングされる前)にjQueryコードを実行するために$ evalAsyncが必要になる場合があります。ブラウザーの後で何らかのアクションを実行する場合は、$timeoutを使用してください。 この回答 を参照してください。ここでは、モデルプロパティを$ watch()するディレクティブの使用方法を示すフィドルを提供し、模擬のfetch()関数で$ evalAsyncを使用しました。

特定のケースでは、最初にディレクティブで次のことを試してみることをお勧めします。

scope.$watch("relatedItems.data", function() {
   $(".Nice-scrollbars").mCustomScrollbar('update');
});

それがうまくいかない場合は、これを試してください:

scope.$watch("relatedItems.data", function() {
   scope.$evalAsync(  // you might need to wrap the next line in a function, not sure
      $(".Nice-scrollbars").mCustomScrollbar('update')
   );
});
14
Mark Rajcok