その他のディレクティブ
これまで紹介したディレクティブ以外にも、より便利なディレクティブや、AngularJS特有の問題の回避をするためのディレクティブなどがあります。
AngularJSでは多くのディレクティブが用意されているために、一通りの使用方法を理解するのも大変ですが、これから紹介するディレクティブは慣れてきたら是非知っておきたいものになります。
外部のテンプレートファイルをテンプレート部品として読み込むディレクティブ - ngInclude
ngIncludeは、HTMLテンプレートを部品化したり、大きなテンプレートを分割するために利用します。外部のテンプレートも通常のテンプレート同様に記述ができます。リスト3は、ngIncludeを使用したサンプルです。
// nginclude.htmlの抜粋 <div ng-init="hello = 'こんにちは'"></div> <div ng-include="'sub_nginclude.html'"></div> <!--(1)変数を利用したインクルード --> <div ng-init="file = 'sub_nginclude.html'"></div> <div ng-include="file"></div> // sub_nginclude.htmlの内容 <div>{{hello}}</div>
固定的なインクルードだけではなく、(1)のように変数を利用したインクルード処理もできるので、簡単な表示の切り分けなどにも利用可能です。
定型文言を切り替えて表示するディレクティブ - ngMessages
ngMessagesは、エラーメッセージやアプリケーション内で共通的に利用するメッセージなどを、テンプレートとして状況に合わせて切り替えて表示するためのディレクティブです。
ngSwitchやngShow/ngHideなど利用しても同じようなことを実現できますが、よりシンプルな記述で利用できるようになっています(*)。
*)ngMessagesはAngularJS 1.4で一部の構文が変更されています。詳しくは、次回の記事で解説します。
リスト4はngMessagesのシンプルな利用例と、メッセージのテンプレート化と同時に複数のメッセージを表示するコード例です。
<!--(1)単純な利用例 --> <div ng-init="pref = {tokyo : true};"></div> <div ng-messages="pref"> 現在地は「 <span ng-message="tokyo">東京都</span> <span ng-message="okinawa">沖縄県</span> 」です </div> <!--(2)再利用する文言をテンプレートとして定義 --> <script type="text/ng-template" id="err-messages"> <div ng-message="required">入力がありません</div> <div ng-message="numeric">数値で入力してください</div> <div ng-message="maxvalue">{{maxval}}以下で入力してください</div> </script> <h4>エラー内容</h4> <!--(3)テンプレートの指定と、複数表示を指定する --> <div ng-init="errors = {required : false, numeric : true, maxvalue : true}; maxval = 100;"></div> <div ng-messages="errors" ng-messages-multiple ng-messages-include="err-messages" class="errors"> </div>
ngSwitchのような単純なケースでの利用の場合には(1)のように記述します。サンプルでは、ng-messagesに表示を制御する為の変数名であるprefを指定しています。
続いてエラーメッセージなどを表示する場合のように、メッセージの外部定義と複数のメッセージを表示する例です。
(2)では再利用するための文言をテンプレートとして定義しています。この定義は説明上直前に定義していますが、idで取得できればどこに記述しても問題ありません。
(3)では、先ほど指定したテンプレート名をng-messages-includeで指定し、複数の項目を表示するためにng-messages-multipleを指定します。この指定を行わないと最初に一致したメッセージのみが表示されます。
また、ngMessagesは外部モジュールとなっているので、angular-messages.jsもしくはangular-messages.min.jsを読みこむことと、ngMessagesのモジュールをリスト5のようにロードすることが必要です。
var app = angular.module('app',['ngMessages']);
![図2 ngMessagesの実行結果](http://cz-cdn.shoeisha.jp/static/images/article/8624/8624_002.gif)
hrefやsrcなどの属性を指定するディレクティブ - ngSrc/ngHref
imgタグやaタグなどでパスを指定する場合にsrcやhrefに値を設定しますが、AngularJSによって{{式}}がパースされる前にこれらの属性があると、ブラウザはそのための処理をしてしまいます。従って、{{式}}の文字列のまま意図しないURLにアクセスすることになってしまい、結果的にアクセスエラーになってしまいます。この問題を回避するためのディレクティブがngSrcとngHrefです。
リスト6は、通常のsrc属性とngSrc属性を使った時のサンプルコードで図3のように、src属性の場合には一瞬だけ画像エラーが表示されてしまう場合がありますが、ngSrcを使えばこの問題が回避できます。また、HTML5ではimgタグはsrcsetという属性もサポートしていますが、その場合にはngSrcsetディレクティブがあるのでそちらを使います。
<div ng-init="url = '../img/sample.png'"></div> <img src="{{url}}" /> <img ng-src="{{url}}" />
![図3 ngSrcの実行結果](http://cz-cdn.shoeisha.jp/static/images/article/8624/8624_003.gif)
同様にhref属性がパース前にリンクが有効にならないようにngHrefディレクティブがありリスト7のように利用できます。
<div ng-init="type = 'type'"></div> <a href="#/{{type}}">パース前にリンクが有効になる例</a><br /> <a ng-href="#/{{type}}">パース後にリンクが有効になる例</a>
記述したままのコードを表示するためのディレクティブ - ngNonBindable
ngNonBindableディレクティブは、{{式}}のような指定をAngularJSでのテンプレート機能を使わず、そのまま文字列として出力したい場合に使用します。
<div ng-non-bindable> <p>{{hoge}}</p> <p>{{hello}} world!</p> </div>
![図4 ngNonBindableの実行結果](http://cz-cdn.shoeisha.jp/static/images/article/8624/8624_004.gif)