
AngularJS 製アプリで jQuery を使いたい
この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

本記事で使用している AngularJS のバージョン
1.2.16
angular.element
先日紹介した ng Global APIs の中に angular.element というメソッドが用意されています。
このメソッドは、デフォルトでは "jQuery lite" または "jqLite" と呼ばれる AngularJS が提供する jQuery のサブセット ( 軽量版 jQuery ) オブジェクトを返しますが、ドキュメントを読む限り制限が多く、困ることが少なくありません。
どのくらい制限されているかというと、、、
https://docs.angularjs.org/api/ng/function/angular.element より
addClass()
after()
append()
attr()
bind()- Does not support namespaces, selectors or eventData
children()- Does not support selectors
clone()
contents()
css()
data()
empty()
eq()
find()- Limited to lookups by tag name
hasClass()
html()
next()- Does not support selectors
on()- Does not support namespaces, selectors or eventData
off()- Does not support namespaces or selectors
one()- Does not support namespaces or selectors
parent()- Does not support selectors
prepend()
prop()
ready()
remove()
removeAttr()
removeClass()
removeData()
replaceWith()
text()
toggleClass()
triggerHandler()- Passes a dummy event object to handlers.
unbind()- Does not support namespaces
val()
wrap()
アプリケーションの仕様によっては、たいへん困る可能性があります。
jqLite を jQuery で上書きする
おそらく開発者も困ると考えていたのでしょうか、逃げ道を用意してくれています。
angular.js
function bindJQuery() {
    // bind to jQuery if present;
    jQuery = window.jQuery;
    // reset to jQuery or default to us.
    if (jQuery) {
        jqLite = jQuery;
        extend(jQuery.fn, {
            scope: JQLitePrototype.scope,
            isolateScope: JQLitePrototype.isolateScope,
            controller: JQLitePrototype.controller,
            injector: JQLitePrototype.injector,
            inheritedData: JQLitePrototype.inheritedData
        });
        // Method signature:
        //     jqLitePatchJQueryRemove(name, dispatchThis, filterElems, getterIfNoArguments)
        jqLitePatchJQueryRemove('remove', true, true, false);
        jqLitePatchJQueryRemove('empty', false, false, false);
        jqLitePatchJQueryRemove('html', false, false, true);
    } else {
        jqLite = JQLite;
    }
    angular.element = jqLite;
}
上記 bindJQuery() メソッドは、angular.js 実行時に 1 度だけ呼ばれる初期化メソッドです。つまり、このメソッドが実行される前に window.jQuery が初期化されていれば良いので…
<script src="jquery.js"></script> <script src="angular.js"></script>
と書いておけば、jqLite は jQuery に上書きされるので OK というわけです。ただし、angular.js 内部で .on() や .off() メソッドを使用しているために 1.7.0 以上のバージョンの jQuery を使用する必要があります。
主にディレクティブ内で使う?
AngularJS では、DOM の参照は常に jQuery または jqLite でラップされ、素の DOM を参照することはありません。ディレクティブ内でもそのルールは守られます。
公式ドキュメントのディレクティブのサンプルでも、しっかり jqLite が使われてます。
- https://docs.angularjs.org/guide/directive#creating-a-directive-that-manipulates-the-dom
- https://docs.angularjs.org/guide/directive#creating-a-directive-that-adds-event-listeners
サンプル
前述の jQuery 上書きサンプルを用意したので貼り付けておきます。jQuery の読み込み行を削除すると、エラーが発生することが確認できるはずです。
絞め
AngularJS が標準で jqLite を採用しているのは、できる限り軽量なフレームワークでありたいという思想があるからだと思います。もちろん、jQuery を使えば大抵の問題はクリアできますが、本当に困るまで我慢した方がエコだと思いますし、なんというか硬派でカッコいい気がするので、それなりに検討してから方針を決めればよいのではないでしょうか。










