お久しぶりです
お久しぶりです、a-knowです。 ブログを書くのは、昨年の12/11以来、半年弱ぶりですか・・・(汗) この半年、本当にいろいろありました。(思い出したくもないこともちらほらと・・・w)
お仕事の方も、今までやっていたPJとは違う、新しいPJが動き始めたということもあって、 バージョン管理をsvnからgitに変えたり(やっと!)、Jenkinsを導入したり、自社開発基盤を刷新したり・・・と、 技術的にも色んな新しいことに挑戦できている毎日なんですが、 AngularJSも、そのうちの一つだったりします。
AngularJSでつまづいたところ
それにしてもAngularJS、非常に痛快ですね! たとえば、jQueryで長々と書いていたDOM操作の為の記述が、ほぼいらなくなっちゃう。これはホントに痛快です。 最近は参加できていませんが、今後ハッカソンやプログラミングコンテストなどの開発スピードが求められるような場に参加した際にも、デフォで使っちゃうだろうなー、というくらいに便利です。
そんな便利なAngularJSなんですが、やはりちょこちょこと躓いたりもしてます。 minify対策なんかもそうなんですが、 最近で一番手間取っちゃったのが、表題の「動的に生成されるDOMに対して、jQueryプラグインの効果を適用する」という点。
jQueryスライダプラグイン「flickslide」を利用するのに手間取った
例をわざわざ用意するのも面倒なので、実際に躓いた事象を挙げます。 利用したのは、jQueryスライダプラグイン「flickslide」。モバイル向けにバナー画像を一定間隔でローテーションさせるUIを生成してくれるプラグインですね。 で、ローテーション対象である画像のDOMをAngularJSで生成している、と。 このflickslideに限らず、こういうかんじのプラグインは多いと思います。
では事例を。htmlはこんな感じで書きます。
<div id="mainImages" class="mainImageInit"> <ul> <li ng-repeat="image in images"> <img ng-src="{{image.imageUrl}}"> </li> </ul> </div>
で、これにflickslideを適用するために、普通ならこう書けばいいんだけど、
$(function(){ $('#mainImages ul li').flickSlide({target:'#mainImages>ul', duration:5000}); });
これだと、AngularJSで動的に生成されたDOMに対して正しく適用させることができない。 どうするか。
directiveを設定するのが正解っぽい。 directiveってなんぞや、ってところですけど、「ng-hoge」みたいなものを自分で定義・設定できるようになる、みたいな感じの理解です。
まず、ng-appを設定して、
<html lang="ja" ng-app="testApp">
directiveを設定。
angular.module('testApp', []) .directive('flSlide', function factory() { return function postLink(scope, iElement, iAttrs) { //ごにょごにょする } }; })
<div id="mainImages" class="mainImageInit"> <ul> <li ng-repeat="image in images" fl-slide> <img ng-src="{{image.imageUrl}}"> </li> </ul> </div>
JSの方で「flSlide」と設定すれば、htmlの方では「fl-slide」と、こういう書き方になります。 んで、「iElement」は、そのdirectiveが設定された要素を指すイメージ。 なのでこの例だと、「images」のサイズが5だと、directiveも5回、呼び出されるかんじ。
この「ごにょごにょ」のところに、実施したいことを記述するわけで、 今回の場合は
$(function(){ $('#mainImages ul li').flickSlide({target:'#mainImages>ul', duration:5000}); });
これに相当することを書きたいわけで、 「iElementは '#mainImages ul li' と同じだから〜・・・」とかいろいろ考えちゃうんですが、 flickslideの場合でいうと、結論、下記のように書くのが正解っぽい。
angular.module('testApp', []) .directive('flSlide', function factory() { return function postLink(scope, iElement, iAttrs) { //最後の一回だけ適用 if(scope.$last === true){ $('#mainImages ul li') .flickSlide({target : '#mainImages>ul', duration : 5000}); } } }; });
自分的には、ずっとiElementを使おうとして(使わなきゃいけないと思って)躓き続けちゃっていました。 元々の記述で行われる処理をdirectiveで実施するだけ、というふうに、はやく頭を切り替えられれば良かった。。
(ちなみにこのflickslideプラグイン、コードにプログラムミスがあると思うんだよなぁ。。いくらdurationに値を設定しても、実際のアニメーションには反映されない。自分で直しちゃったけど。。)
おまけ・AngularJSを使って開発をスタートするためにやったこと
ドットインストール。全部見ても30分。全くの予備知識もないところに見るのには最適。 公式サイト。APIリファレンスがすごく探しやすい。最終的な検索結果とはあまり関係のないワードを入力しても、結構目的のページに行き着けちゃう印象。
・・・僕はこれだけ。w あとはひたすら作る!手を動かす!・・・これですね☆
(仕事仲間もつぶやいてたんだけど、例えばng-controllerの好ましい設定範囲は?とか、AngularJSに関してはまだまだ疑問は尽きないかんじ。ぜひ勉強会とかに参加して基礎を固めたいな、というところ。)
関連エントリ
はじめてのAngularJS―「双方向データ結合」&「依存性注入」 「Mode」「View」「Controller」に分離して作業を明確化! (I・O BOOKS)
- 作者: 吉田徹生
- 出版社/メーカー: 工学社
- 発売日: 2013/12/01
- メディア: 単行本
- この商品を含むブログ (3件) を見る
- 作者: 池添明宏,金井健一,吉田徹生,丸山弘詩
- 出版社/メーカー: インプレス
- 発売日: 2014/09/05
- メディア: 単行本(ソフトカバー)
- この商品を含むブログを見る
- 作者: 外村和仁
- 出版社/メーカー: マイナビ出版
- 発売日: 2014/10/06
- メディア: Kindle版
- この商品を含むブログを見る