MEANスタックを用いたWebアプリの開発方法について紹介していく連載。今回は、AngularJSにデフォルトで用意されている便利なディレクティブの使い方をサンプルコードと共に紹介する。
前回の記事、「AngularJSの理解で欠かせないコントローラーとas記法、データバインディングの基本的な使い方」では、AngularJSのコントローラーとデータバインディングについて紹介しました。今回はAngularJSが最初から持っているディレクティブ(ビルトインディレクティブ)について解説します。
なお、本記事を見て実際にサンプルを動かしたい場合は、以前の連載記事(第1回、第2回)を見て環境を作成しておきましょう。
以前の記事で解説しましたが、AngularJSではHTMLを拡張する仕組みが提供されており、これを使用して作成された機能を「ディレクティブ」と呼びます。
AngularJSには、デフォルトで多数の便利なディレクティブ(ビルトインディレクティブ)が用意されています(※以前使用した「ng-app」「ng-model」はビルトインディレクティブです)。
このビルトインディレクティブを使用することにより、AngularJSの便利な機能が簡単に使用できるようになります。本記事では、よく使用されるビルトインディレクティブを紹介していきます。
動作確認をするためのサンプルコードですが、以前と同じく連載第6回の「いまさら聞けないAngularJSの基礎知識と5つの主な特徴、インストール、簡単な使い方」で作成した「simple-angular」プロジェクトを使用します。
ngIfディレクティブを使用すると、結果がfalseと判断された際、定義したDOMをツリーから削除します。その後ngIfの結果がtrueになった場合、削除されたDOMが再び元の場所に追加されます。
では、simple-angular/index.htmlを下記のように記述してください。
<!DOCTYPE html> <html ng-app> <head> <script src="bower_components/angular/angular.js"></script> </head> <body> <input type="checkbox" ng-model="checkbox"> 表示の切り替え <p ng-if="checkbox">チェックボックス ON</p> </body> </html>
上記ファイルをブラウザで表示してみましょう。チェックボックスをチェックするとng-if内の文字列が表示され、チェックを外すと文字列が消えます。
なお、これに似たディレクティブとして「ngHide」がありますが、これはDOM要素のstyle属性を「display:none」とするだけです(ngIfの場合はDOMツリーから削除。スコープも再作成されます)。
このディレクティブは、多くのプログラミング言語でよく見掛ける「swich文」と同様の機能を持っており、分岐処理を記述できます。下記のような3つの属性を組み合わせて使用します。
では、simple-angular/index.htmlを下記のように記述してください。
・ ・ <body> <input type="radio" ng-model="season" value="spring"> 春 <input type="radio" ng-model="season" value="summer"> 夏 <input type="radio" ng-model="season" value="autumn"> 秋 <input type="radio" ng-model="season" value="winter"> 冬 <div ng-switch='season'> <div ng-switch-when='spring'>桜</div> <div ng-switch-when='summer'>海</div> <div ng-switch-when='autumn'>紅葉</div> <div ng-switch-when='winter'>雪</div> <div ng-switch-default>季節を選択してください</div> </div> </body> ・ ・
初期状態ではng-switch-whenに該当するデータがないので、defaultの内容が表示されますが、ラジオボタンを選択することで、それに合ったng-switch-whenの内容が表示されます。
このディレクティブは、ループ処理を実行するためのディレクティブです。コレクションの繰り返し処理を行ったり、ループインデックスの取得も可能になっています。
ng-repeat属性では次の2種類の指定方法があります。
ng-repeat = '変数 in 式'
ng-repeat = '(キー, 値) in 式'
では、simple-angular/index.htmlを編集し、動作を見てみましょう。
・ ・ <body> <p>1.コレクションの表示</p> <ul ng-init="users=['taro','hanako','syuta']"> <li ng-repeat="user in users">{{user}}</li> </ul> <p>2.オブジェクトの表示</p> <ul ng-init="myData = { id:10 , name = 'syuta' , age = '36', lang = ['javascript','Java','Scala'] }"> <li ng-repeat="(key, value) in in myData">{{ key }} : {{ value }}</li> </ul> <p>3.ngRepeatの変数を使用</p> <table ng-init=" numbers = ['one','two','three','four','five'] "> <thread><tr><td>value</td><td>index</td></tr></thread> <tr ng-repeat="num in numbers"> <td>{{num}}</td> <td>{{$index}}</td> </tr> </table> </body> ・ ・
「1.コレクションの表示」では、usersコレクションをliタグで1件ずつ表示しています。また、「2.オブジェクトの表示」ではオブジェクトのプロパティをkeyとvalueにバインドして表示しています。「3.ngRepeatの変数を使用」では、「$index」という変数を使用して、コレクションのインデックスを表示しています。
ngRepeatでは、この$index以外にも、下記を使用できます。
先ほどngRepeatについて解説しましたが、ngClassEven/ngClassOddディレクティブは、このngRepeatと組み合わせて使用します。ngClassEvenはngRepeat使用時、偶数行でtrueになり、ngClassOddは奇数行でtrueになります。
下記サンプルを実行すると、liタグに対してCSSが順番に適用されます。
・ ・ <body> <style> .bluecolor { color : blue;} .redcolor { color : red; } </style> <ul ng-init="languages=['Java','Ruby','Python']"> <li ng-repeat="lang in languages" ng-class-even="'bluecolor'" ng-class-odd="'redcolor'"> {{ lang }} </li> </ul> </body> ・ ・
最近はテーブルやリストの偶数行と奇数行で別のスタイルを充てていることが多いですが、このディレクティブを使用すれば簡単にできます。
これらのディレクティブはメッセージを扱うためのディレクティブで、条件に応じてメッセージの表示を切り替えることができます。
下記例を見てください。「$scope.myMessages」に設定してあるキーがtrueのときだけ、ng-messageが表示されます。
<html ng-app = 'mySimpleApp'> <head> <script src="bower_components/angular/angular.js"></script> <script src="bower_components/angular-messages/angular-messages.js"></script> </head> <script> angular.module('mySimpleApp', [ 'ngMessages' ]) .controller('myController', ['$scope', function($scope) { $scope.myMessages= { 'msg1':true, 'msg2':false, 'msg3':true }; }]); </script> <body ng-controller="myController"> <div ng-messages="myMessages" ng-messages-multiple> <p ng-message="msg1">Message1</p> <p ng-message="msg2">Message2</p> <p ng-message="msg3">Message3</p> </div> </body> </html>
ここでは、myMessages.msg1とmyMessages.msg3がtrueなので、「Message1」と「Message3」が表示されます(※「ng-messages-multiple」がない場合、最初にマッチしたキーのng-messageのみ表示)。
ngStyleはstyle属性を操作するためのディレクティブです。下記例ではクリックのタイミングでstyleがテキストに適用されます。
・ ・ <body> <p ng-style='myNgStyle'>ngStyleのテスト</p> <input type='button' ng-click="myNgStyle = {color:'red'} " value='スタイル適用'/> </body> ・ ・
ngStyleはstyle属性を操作しましたが、ngClassはいくつかの方法でCSSを扱えるディレクティブです。具体的には、次のような3種類の定義方法があります。
それぞれの使い方を確認してみましょう。
・ ・ <body> <style> .bluecolor { color : blue;} .bold {font-weight: bold; } </style> <p ng-class="'bluecolor'">通常のCSS的な定義方法</p> <p ng-class="['bluecolor','bold']">配列を使用した定義方法</p> <p ng-class="{ bluecolor : false, bold : true }"> オブジェクト形式での定義方法</p> </body> ・ ・
通常のCSS的な定義方法では、styleタグ内で定義してあるclassをng-classで指定しています。また、配列で複数組み合わせて使用することも可能になっています。
オブジェクト形式での定義を指定している箇所では、ng-classでkeyにcssのクラス名、valueに真偽値を指定しています。この値がtrueの場合、対応するcssのクラスが適用されることになります。
上記例では、bluecolorがfalse、boldがtrueなので、boldだけが適用されることになります。
ngClickディレクティブは「click」イベントリスナーを、ngDblClickは「dblclick」イベントリスナーをそれぞれ登録します。
次のサンプルでは、Controllerに定義した関数をイベントにひも付けて実行しています。
・ ・ <script> angular.module('mySimpleApp', []) .controller('myController', ['$scope', function($scope) { //ngClickの定義 $scope.clk= function() { alert("click!"); }; //ngDblclickの定義 $scope.dblClk= function() { alert("double click!"); }; }]); </script> <body ng-controller="myController"> <!-- クリックイベント --> <button ng-click="clk()"> クリックイベント </button> <!-- ダブルクリックイベント --> <button ng-dblclick="dblClk()"> ダブルクリックイベント </button> </body> ・ ・
このディレクティブはsubmitイベントのためのディレクティブです。対象のフォームにaction属性が設定されていない場合、サブミットアクション(フォーム情報をサーバへ送ってページ遷移する動作)は行われません。
次のサンプルでは、フォームにng-submitを設定しています。
・ ・ <script> angular.module('mySimpleApp', []) $scope.submit= function() { console.log("mytext = " + $scope.mytext); }; }]); </script> <body ng-controller="myController"> <form ng-submit="submit()"> <input type="text" ng-model="mytext" name="text" /> <input type="submit" value="Submit" /> </form> </body> ・ ・
上記サンプルではaction属性が設定されていないので、サブミットボタンを押しても画面遷移は行われません。
href属性に対して動的にURLを設定したい場合、エクスプレッション構文を使って指定することがあります。その場合、値が設定されるまでURLは空の状態ですがアンカーは貼られているという状態になってしまい、あまり良くありません。
そんなときにngHrefディレクティブを使用すると、値が設定されていない場合はリンクが有効にならないので、クリックされるのを防ぐことができます。
次のサンプルを確認してみてください。初期状態ではurlの値が空なのでリンクは無効ですが、ボタンをクリックしてurlを設定した時点でリンクが有効になります。
・ ・ <script> angular.module('mySimpleApp', []) .controller('myController', ['$scope', function($scope) { $scope.url = ""; $scope.setLink= function() { $scope.url = "http://atmarkit.co.jp"; }; }]); </script> <body ng-controller="myController"> <a ng-href="{{url}}">ng-hrefを使ったリンク</a> <input type="button" ng-click="setLink()" value="set rink" /> </body> ・ ・
今回はAngularJSのビルトインディレクティブについて紹介しました。今回紹介した以外にも、さまざまなビルトインディレクティブがありますので、公式ドキュメントなどで確認してみてください。
AngularJSには、さまざまなディレクティブが用意されており、基本的な機能は大体そろっています。そのため、実現したい機能がある場合、まずはビルトインディレクティブにその機能がないか確認してみてください。
また、ビルトインディレクティブの機能では要件を満たせない場合、自分でディレクティブを作成する(カスタムディレクティブ)ことも可能です。その方法については次回以降の記事で紹介する予定です。
Copyright © ITmedia, Inc. All Rights Reserved.