AngularJS は、下記の様な特徴を持つ JavaScript フレームワークのひとつです。
これまでのWebサービスでは、サーバ側で画面(HTML/DOM)を生成していたのに対し、最近のWebサービスでは、サーバ側はDB操作のみを処理し、クライアント-サーバ間をAjaxでJSON交換し、画面(HTML/DOM)はクライアント側で生成する方式が増えてきました。AngularJSは、クライアント側 JavaScript のコントローラでデータモデルを管理し、画面(ビュー)とリアルタイムにデータを交換するのに適したフレームワークです。
AngularJSの簡単なサンプルを下記に示します。AngularJSは、ng-app を指定した要素の中で使用します。ng-model="yourName" に入力した文字列が、{{yourName}} の箇所に表示されます。
<!doctype html> <html ng-app> <head> <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.4/angular.min.js"></script> </head> <body> <div> <p><input type="text" ng-model="yourName"></p> <p>Hello {{yourName}}!</p> </div> </body> </html>
Hello {{yourName}}!
下記の様に、{{...}} の中で、JavaScript の式を記述することができます。
<!doctype html> <html ng-app> <head> <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.4/angular.min.js"></script> </head> <body> <div><input type="text" ng-model="x"></div> <div><input type="text" ng-model="y"></div> <div>{{x}} vs {{y}} : {{( x > y ) ? x : y}} is big.</div> </body> </html>
値を表示する際に、いくつかのフィルタを使用することができます。
<!doctype html> <html ng-app> <head> <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.4/angular.min.js"></script> </head> <body> {{12345678|number}} // カンマ区切り => 12,345,678 {{12.34|number:4}} // 少数以下4桁 => 12.3400 {{12.34|currency}} // 通貨 => $12.34 {{1234|currency:'¥'}} // 通貨(円記号) => ¥1,234.00 {{'2099-12-31T12:59:59'|date}} // 日付フォーマット => Dec 31, 2099 {{'2099-12-31T12:59:59'|date:'yyyy/MM/dd'}} // 日付フォーマット => 2099/12/31 {{[1,2,3,4]|limitTo:3}} // 最初の3件のみ表示 => [1,2,3] {{"Yamada"|lowercase}} // 小文字変換 => yamada {{"Yamada"|uppercase}} // 大文字変換 => YAMADA {{{name:"Yamada", age:36}|json}} // JSON形式で表示 => { "name": "Yamada", "age": 26 } {{[1,3,5,2,4]|orderBy}} // ソートして表示 => [1,2,3,4,5] {{[1,3,5,2,4]|orderBy:'':true}} // 逆順ソートして表示 => [5,4,3,2,1] </body> </html>
フィルターに関する詳細は下記を参照してください。
下記では、モジュールとコントローラを利用した例を示します。ng-app でアプリケーションを指定し、ng-controller でコントローラを指定します。コントローラの中で $scope に定義した変数を {{...}} で使用することができます。
<!doctype html> <html> <head> <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.4/angular.min.js"></script> <script> var app = angular.module('myApp', []); app.controller('myController', function($scope) { $scope.message = 'Hello world!'; }); </script> </head> <body> <div ng-app="myApp"> <div ng-controller="myController"> {{message}} </div> </div> </body> </html>
AngularJS 1.2 以降では、$scope ではなく this を用いて、次のように記述することが可能で、最近ではこの記法が主に使用されています。呼び出す側は as を用いてオブジェクトを定義し、オブジェクトのプロパティとして値を参照します。この形式により、複数のコントローラを利用する場合に $scope の範囲が不明確になるのを防ぐことができます。
<!doctype html> <html> <head> <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.4/angular.min.js"></script> <script> var app = angular.module('myApp', []); app.controller('myController', function() { this.message = 'Hello world!'; }); </script> </head> <body> <div ng-app="myApp"> <div ng-controller="myController as myCtrl"> {{myCtrl.message}} </div> </div> </body> </html>
ng-repeat を用いて、リスト操作を行うことができます。
<!doctype html> <html ng-app="myApp"> <head> <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.4/angular.min.js"></script> <script> var app = angular.module('myApp', []); app.controller('myController', function() { this.members = [ { name: 'Tanaka', age: 36 }, { name: 'Suzuki', age: 16 }, { name: 'Yamada', age: 26 } ]; }); </script> </head> <body> <div ng-controller="myController as myCtrl"> <ul> <li ng-repeat="member in myCtrl.members">{{member.name}} {{member.age}}</li> </ul> <div>{{myCtrl.members.length}} members</div> </div> </body> </html>
orderByフィルタを用いて、age でソートして表示することが可能です。
<li ng-repeat="member in myCtrl.members|orderBy:'age'">{{member.name}} {{member.age}}</li>
orderByフィルタの第二引数に true を指定すると逆順にソートします。
<li ng-repeat="member in myCtrl.members|orderBy:'age':true">{{member.name}} {{member.age}}</li>
filter を用いることで、要素をフィルタリングして表示することができます。下記の例では、テキストフィールドに入力した文字にマッチする要素のみを表示します。
<!doctype html> <html ng-app="myApp"> <head> <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.4/angular.min.js"></script> <script> var app = angular.module('myApp', []); app.controller('myController', function() { this.members = [ { name: 'Tanaka', age: 36 }, { name: 'Suzuki', age: 16 }, { name: 'Yamada', age: 26 } ]; }); </script> </head> <body> <div ng-controller="myController as myCtrl"> <input type="text" ng-model="searchText"> <ul> <li ng-repeat="member in myCtrl.members|filter:searchText">{{member.name}} {{member.age}}</li> </ul> </div> </body> </html>
ng-click などで、コントローラに定義したアクションを呼び出すことができます。
<!doctype html> <html ng-app="myApp"> <head> <title>TEST</title> <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.4/angular.min.js"></script> <script> var app = angular.module("myApp", []); app.controller('myController', function() { this.count = 0; this.inc = function() { this.count++; } this.dec = function() { this.count--; } }); </script> </head> <body> <div ng-controller="myController as myCtrl"> {{myCtrl.count}} <button ng-click="myCtrl.inc()">+1</button> <button ng-click="myCtrl.dec()">-1</button> </div> </body> </html>
フォームに対して様々なバリデーションルールを記述することができます。下記の例では、テキストが必須(required)であること、最少文字数(minlength)が3文字、最大文字数(maxlength)が8文字であることを示しています。それぞれのバリデーションがエラーになると、対応するエラーメッセージを表示します。novalidate は HTML 本来のバリデーションを実行せず、AngularJS のバリデーションにまかせることを意味します。
<!doctype html> <html ng-app> <head> <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.4/angular.min.js"></script> </head> <body> <form name="myForm" novalidate> <div><input type="text" name="text1" ng-model="sampleText" ng-required="true" ng-minlength=3 ng-maxlength=8></div> <div ng-show="myForm.text1.$error.required">Required!</div> <div ng-show="myForm.text1.$error.minlength">Too short!</div> <div ng-show="myForm.text1.$error.maxlength">Too long!</div> </form> </body> </html>
各フォームで使用可能なバリデーションルールは、下記等を参照してください。
下記は、名前と年齢を入力して Add ボタンを押すとリストに追加し、チェックボックスをチェックして Del ボタンを押すとリストから削除するサンプルです。最後に {{myCtrl|json}} でコントローラの内容をデバッグ用に表示しています。
<!doctype html> <html ng-app="myApp"> <head> <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.4/angular.min.js"></script> <script> var app = angular.module("myApp", []); app.controller("myController", function() { this.members = [ { name:"Tanaka", age:16 }, { name:"Yamada", age:26 }, { name:"Suzuki", age:36 }, ]; this.onAdd = function() { this.members.push({ name:this.name, age:this.age }); this.name = this.age = ""; }; this.onDel = function() { for (var i = 0; i < this.members.length; i++) { if (this.members[i].checked) { this.members.splice(i--, 1); } } }; }); </script> </head> <body ng-controller="myController as myCtrl"> <div> <input type="text" ng-model="myCtrl.name">(<input type="text" ng-model="myCtrl.age">) <button ng-click="myCtrl.onAdd()">Add</button> </div> <div ng-repeat="member in myCtrl.members"> <input type="checkbox" ng-model="member.checked">{{member.name}}({{member.age}}) </div> <div><button ng-click="myCtrl.onDel()">Del</button></div> <hr><pre>{{myCtrl|json}}</pre><hr> </body> </html>
{{myCtrl|json}}
ng-app を指定した要素の中では、{{ ... }} が AngularJS により解釈されてしまいます。解釈せずに表示するには、下記の様に、バックスラッシュ(\)でエスケープした文字で表示する、}} の間にHTMLのコメントを挿入する、ngNonBindable ディレクティブを用いるなどの方法があります。(ngBindable がサポートされていれば、デフォルトで NonBindable にして、解釈したい箇所だけ Bindable にできるのですが・・・)
{{'\{\{name\}\}'}} {{name}<!-- -->} <span class="ng-non-bindable">{{name}}</span>