基本のディレクティブ
データバインディング(データをテンプレート側に表示)をする際に必要な基本のディレクティブです。
モデルをテンプレートにバインドする基本のディレクティブ - ngBind
ngBindはモデル(データ)をHTMLテンプレートバインドする基本的なディレクティブです。属性にng-bindとして指定する以外にも、{{式}}でも同様の表示ができるので、こちらを利用するケースが多くなるかと思います。
しかしながら、要素のテキストとして指定した場合に一瞬ですが、{{式}}のテキストが表示されてしまうことがあります。属性に指定することで、この問題を回避できます。この問題を回避するには後述するngCloakを利用することで回避することもできます。
また、あまり、オススメはできませんが、クラス名に「ng-bind:」とする事でも利用可能です。ただし、他のディレクティブでクラス名での指定が利用できるとは限らないので、属性で指定する方が好ましいでしょう。
<div ng-init="hello = 'こんにちは'"></div> <!-- 後述のngInitを参照 -->
<table>
<tr><td>属性にモデルを記述した場合</td><td><span ng-bind="hello"></span></td></tr>
<tr><td>class属性を使用した場合</td><td><span class="ng-bind: hello"></span></td></tr>
</table>
テンプレート形式でバインドするモデルを指定できるディレクティブ - ngBindTemplate
ngBindTemplateは、テンプレート形式(=式以外の文字列を含んだ形式)を指定できるディレクティブです。
ngBindとほぼ同様ですが、属性にテンプレート形式の記述方法でバインドできる点が異なります。
<div ng-init="hello = 'こんにちは'"></div>
<p ng-bind-template="{{hello}} world!"></p>
<!-- 以下の指定と同じ結果が得られます -->
<p>{{hello}} world!</p>
記述した式の記述がちらつく現象を抑制するディレクティブ - ngCloak
ngCloakモジュールは、リファレンスだけを見ていても少々分かりにくいディレクティブですが、実際にテンプレート機能を使っていると、表示上に、一瞬だけ"{{式}}"のように実際に記述した内容が見えてしまう場合があります。この問題は、先に述べたようにng-bindやng-bind-templateなどの属性を使って指定することでも回避できますが、ngCloakディレクティブを使うことでも回避できます。
<div ng-init="hello = 'Hello'"></div>
<div ng-cloak>
<p>{{hello}} World</p>
</div>
このディレクティブはCSSを使って実現されていて、リスト5(ngCloakが使用しているCSSの定義)のCSSをAngularJSが自動で生成しています。テンプレートのパースが終了し、{{式}}の表示がされない工程になった時にngCloakが指定された要素を表示するようにすることでチラツキが起きないようにしています。
従ってng-cloakをbody要素など表示全体に指定はしないほうが望ましいです。
[ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak {
display: none !important;
}
HTMLコードをテンプレートにバインドする - ngBindHtml
ngBindHtmlはHTMLコードを含んだ文字列をHTMLのままバインドするためのディレクティブです。ngBindやngBindTempalteでは、危険なHTMLコードを含んだ文字列は自動的にエスケープされてしまいます。これは出力するHTMLを安全にするためのAngularJSの機能なのですが、意図的にHTMLを出力したいケースがあります。この場合にngBindHtmlを使うことで、安全にHTMLのコードをテンプレートにバインドできます。
ngBindとngBindHtmlを使って「<a href='javascript:alert("click")'><b>Hello</b></a>」というコードをバインドしたコードと結果が、リスト6(ngBindHtmlの利用例)と図3(ngBindHtmlの実行結果)です。
<table>
<tr><td>ngBindの場合</td><td>{{helloHtml}}</td></tr>
<tr><td>ngBindHtmlの場合(通常)</td><td><span ng-bind-html="helloHtml"></span></td></tr>
<tr><td>ngBindHtmlの場合(trustAsHtml)</td><td><span ng-bind-html="helloTrustHtml"></span></td></tr>
</table>
ngBindではエスケープされてしまっていますが、ngBindHtmlを使えばエスケープされずに出力されています。ngBindHtmlの出力例として(通常)と(trustAsHtml)と記載された物では表示が若干異なる事に気がついたでしょうか?
この2つの違いはDOM上に構築されたHTMLコードを見ればすぐにわかります。リスト7(ngBindHtmlで生成されたHTMLコード)に注目してください。
<a><b>Hello</b></a>
<a href='javascript:alert("click")'><b>Hello</b></a>
この出力の違いを含めて、このディレクティブ機能を使うには若干の注意点がありますので、それらを含めて説明します。
まず、このディレクティブを使うにはngSanitizeモジュールが必要でリスト8のように追加のJavaScriptソースを読み込む必要があります。
//(1)HTMLでの指定
<script type="text/javascript" src="vendors/angular-sanitize.js"></script>
//(2)AngularJSでngSanitizeモジュールを指定
var app = angular.module('app',['ngSanitize']);
HTML側には(1)のようにangular-sanitize.jsもしくは、angular-sanitize.min.jsを読み込みます。続いて、(2)のようにmoduleメソッドにngSanitizeを指定するとモジュールの組み込みは終了です。
コントローラ側の使い方はリスト9のようになります。
module.controller('ngBindHtmlController',['$scope','$sce',function($scope,$sce){
var html = "<a href='javascript:alert(\"click\")'><b>Hello</b></a>"; // ・・・(1)
$scope.helloHtml = html; //・・・(2)
$scope.helloTrustHtml = $sce.trustAsHtml(html); // ・・・(3)
}]);
出力するHTMLコードは(1)のようなコードとします。(2)のようにそのままの設定にすると、先の(通常)出力となります。つまり、XSS等の危険性があるコードが削除されてしまいます。そのため、属性が除去されてタグの要素名とHelloという文字列だけになるので結果的に太字でHelloという見え方になります。
ユーザが入力フィールドなどを通じてHTMLコードを部分的に登録するケースでは、これらの安全機能は非常に有効ですが、プログラマが意図的に記述したような場合にはこれでは問題があります。
そこでHTMLコードが安全であることが保証できる場合には、(4)のようにtrustAsHtmlメソッドを使い、安全性をプログラマが保証すれば指定したコードがそのまま表示されます。このようにHTMLコードを扱うのは多少面倒ではありますが、一方で安全な利用ができるように考慮されています。
この機能は$sceというサービスを利用しています。この"sce"は、Strict Contextual Escapingの略であり、コンテキスト(例えば、HTMLやJavaScriptなど)に応じてエスケープや出力を制限するための機能で、ここで紹介したHTMLコード以外の使い方もありますので詳しくはリファレンスを参照してください。
テンプレート内で変数の定義など、式の実行をするディレクティブ - ngInit
ngInitは指定された式を実行するディレクティブです。今までのサンプルでも使ってきましたが、コントローラを通さずに値を設定したい場合などには有効な方法です。
<div ng-init="hello = 'こんにちは';">
<span>{{hello}}</span>
</div>

