SlideShare una empresa de Scribd logo
1 de 58
AngularJS 入門
2015年11月3日 版
(株)シナジークエスト
白根健司
AngularJS 入門
AngularJS を使ってみる
Obserever パターンと UI 設計
• Observer パターン
– Observer: Subject の変更を監視し、変更時に表示を更新する
– Subject: データを保持し、Observer の登録・削除メソッドを持つ
• Model-View
– UI 設計に Observer パターンを適用
• 表示機能(View)と表示対象データ(Model)とに分割し、
• 0 個以上の View が Model を observe する構造で UI を構成する
view1
modelview2
view3
Observer Subject
+notify()
+notifyObserves()
+addObserver()
+deleteObserver()
*
①Model を操作
(データの変更発生)
②Model は変更したことを View に通知する
③View は Model から変更後のデータを取得して表示更新
MVC パターン
• MVC パターン
– Model(ビジネスロジック)、View(ユーザーインターフェイス)、
Controller(Model と View の仲立ち)の3つの責務に基づいて
アプリケーションを構成する設計パターン
要素 責務(役割)
Model(モデル) アプリケーションが扱うデータの管理と操作を受け持つ。
データを操作するための機能(ビジネスロジック)を提供する。
View(ビュー) ユーザーインターフェイスに対応する部分。
ユーザーからの入力受付と結果の表示を担当する。
Controller(コントローラ) Model と View の両方に関連を持ち、処理の流れを制御す
る役割を受け持つ。View から受け取ったデータを Model に
渡し、表示の更新が必要な Model の変更を View に通知
する。
(参考)Model2(MVC2)
• Model2
– MVC をサーブレット/JSP 等の Web システム構造に適用したもの
• JSP 仕様のドラフトにおいて提唱された(1998年)
– 実質的な UI であるブラウザにモデルの変更が通知される仕組みはない
(Observer パターンになっていない)
Controller
View
Model転送
操作
参照
ブラウザ
要求
応答
Model-View-Controller
View
Conroller Model
ユーザー操作
呼び出し
操作
変更通知
Observer パターンの
Subject
Observer パターンの
Observer
Model の変更を View に
通知して表示を更新させる
Observer パターンの構造が基本。
Model の変更を View に通知する
仕組みを実装する必要がある。
MVVM:Model-View-ViewModel
• MVVM:MVC の派生パターン
– View
• ユーザーからの入出力操作を
受け付ける UI
– ViewModel
• 表示用の状態データ
– View と同期(データバインディング)
• View からの入力を
Model に反映させる役割
– Model
• アプリケーション固有の部分
– ビジネスロジック
– データ
View
ViewModel
Model
ユーザー操作
データバインディング
ユーザー
インターフェイス
表示用データ
ビジネスロジック
データ
操作 取得
JavaScript MVC/MVVM フレームワーク
• AngularJS
– フルスタックの JavaScript MVC フレームワーク
• React
– Facebook によるフレームーワーク。View の機能を提供する。
• Backbone.js
– シンプルな構造が特徴のフレームワーク。
• Knockout.js
– ASP.NET SPA アプリに標準対応したフレームワーク
• Ember.js
– フルスタックのフレームワーク
AngularJS とは
• AngularJS とは
– JavaScript によるアプリケーション フレームワーク
– MVC に基づくクライアントアプリケーション開発をサポート
– 入手先
• https://angularjs.org/
• 特徴
– Google を中心に開発されている
– ドキュメント/関連ライブラリの充実
– フルスタック
• MVC 構造のほか
アプリ開発に必要な種々の機能
AngularJS を使用するには
• script タグの href 属性に指定してインポート
– CDN 経由
– コピーを取得
• ダウンロード
• Bower で取得
• npm で取得
AngularJS を使ってみる
AngularJS の中核機能
• テンプレート
– ディレクティブ
– AngularJS 式
– データバインディング
• View-ViewModel
– 反復表示
• ng-repeat
– フィルタ
• MVC
– Controller
– テンプレートとの関連付け
– サービス
• ビジネスロジックの分離
– 依存性注入
• Dependency Injection
– ルーティング
ステップ1:テンプレートとディレクティブ
• テンプレート
– MVC の View となるページを記述する
• HTML の拡張構文を利用する
• AngularJS の HTML 構文拡張
– AngularJS 式: {{ <式> }}
• AngularJS の処理系が式を評価し、その結果に変換される
– ディレクティブ
• DOM 要素(属性、HTML タグ名、コメント、CSS クラス)のマーカー
• 指定した DOM 要素に特定の振る舞いを関連付ける働きを持つ
• 双方向データバインディング
– テンプレートの要素と表示用データを相互に同期させる仕組み
• MVVM における View と ViewModel の関係
Intro of
this step
サンプル:テンプレート HTML
• ajs00_template.html
– テンプレート出発点:AngularJS 適用前の普通の HTML
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>サンプル00</title>
</head>
<body>
<h1>3 + 4</h1>
</body>
</html>
サンプル:AngularJS 式
• ajs01_expression.html
– AngularJS 式で 「3+4」 を評価させる例
<!DOCTYPE html>
<html ng-app>
<head>
<meta charset="UTF-8" />
<title>サンプル01</title>
<script src="angular.min.js"></script>
</head>
<body>
<h1>{{3 + 4}}</h1>
</body>
</html>
ng-app ディレクティブ
AngularJS を初期化し、処理対象のルート要素を指定する
AngularJS 式:{{ ~ }}
AngularJS による評価結果が表示される式
サンプル:双方向データバインディング
• ajs02_databinding.html
– 双方向バインディングの例
• ng-model ディレクティブを指定した input 要素と変数 name との間で
データバインディングをする例
<!DOCTYPE html>
<html ng-app>
<head>~</head>
<body>
名前:
<input type="text" ng-model="name" /> {{name}}
</body>
</html>
ng-model ディレクティブ
input、select、textarea の各要素を
変数(=スコープのプロパティ:後述)にバインドする。
変数が存在しない場合は新たに定義される。
ng-model でバインドした変数の評価式:
input タグの入力値が自動的に反映される。
name 変数が変更されると逆に input 要素が更新される
ステップ1:ポイントまとめ
• テンプレート
– 拡張版の HTML でテンプレートを記述する
• AngularJS がテンプレートを読み込んで処理した結果が表示される
• AngularJS 式:{{ }}
– {{ と }} で囲んで記述した式のこと
• 式を評価した結果が表示される
• ディレクティブ
– DOM 要素に特定の振る舞いを関連付けるマーカー
• ng-app ディレクティブ
– AngularJS の初期化と処理対象のルート要素を指定する
• ng-model ディレクティブ
– input、select、textarea の各要素と変数をバインドして相互に値を同期させる
ステップ2:反復表示
• ng-repeat ディレクティブ
– コレクションを全件処理する
• 配列の要素
• オブジェクトのプロパティ
• ng-init ディレクティブ
– 代入式などの式を現在のスコープ内で評価(実行)する
• スコープ内の変数の初期化に用いられる
Intro of
this step
サンプル:配列の反復処理
• ajs03_repeat1.html
– 配列を反復処理して要素を全件表示する例
<!DOCTYPE html>
<html ng-app>
<head>~</head>
<body>
<ul>
<li ng-repeat="item in ['太郎', '次郎', 'ぜんじろう']">
項目{{$index}} = {{item}}
</li>
</ul>
</body>
</html>
「変数 in 配列」 の
形式で属性に指定
ng-repeat ディレクティブ
この属性を含む要素(li)を反復出力する
$index 予約変数
反復処理の中で各要素の
インデックスが設定される
サンプル:オブジェクトのプロパティの読み出し
• ajs04_repeat2.html
– オブジェクトのプロパティを順次読み出す例
<!DOCTYPE html>
<html ng-app>
<head>~</head>
<body>
<ul>
<li ng-repeat="(k,v) in {name:'太郎',age:25}">
{{k}}の値 = {{v}}
</li>
</ul>
</body>
</html>
オブジェクトのリテラル
1番目の変数(この例では k):プロパティ名
2番目の変数(この例では v):プロパティの値
AngularJS 式で変数を参照
サンプル:in の後を変数に置換
• ajs05_repeat3.html
– in の後にリテラルではなく変数を配置する例
<!DOCTYPE html>
<html ng-app>
<head>~</head>
<body ng-init="obj={name:'太郎',age:25,address:'札幌'}">
<ul>
<li ng-repeat="(k, v) in obj">
{{k}}の値 = {{v}}
</li>
</ul>
</body>
</html>
変数 obj へのオブジェクトリテラルの代入式を
ng-init ディレクティブで評価(実行)する
上記の代入式で初期化された変数 obj を
反復処理の対象オブジェクトとして指定している
ステップ2:ポイントまとめ
• ng-repeat ディレクティブ
– 配列の要素を順次取得して反復処理を行う
• 例)<div ng-repeat="member in group">~</div>
– group:集合
– member:集合の要素が順次代入される変数
– オブジェクトのプロパティを順次取得して反復処理を行う
• 例)<div ng-repeat="(key, value) in object">~</div>
– key:オブジェクトのプロパティ名
– value:プロパティの値
– objcet:プロパティを取り出す対象のオブジェクト
※1)いずれも ~ の部分で {{ }} 式を用いて要素やプロパティの値を出力できる
※2)特別に予約された変数 $index で処理中の要素のインデックスを取得できる
• ng-init ディレクティブ
– 代入式などの式を現在のスコープ内で評価(実行)する
ステップ3:フィルタ
• フィルタとは
– 式の値を通過させることで、
• 書式の設定
• 値の変換
• 条件に該当しないものの除外
• 並べ替え
・・・
など変更を加えた結果を取得する機能
– 表記法
• パイプ記号(|)で作用させる
– {{ 式 | フィルタ1 | フィルタ2 | フィルタ3 }}
• コロン (:) でフィルタに引数を渡すこともできる
– {{ 式 | フィルタ:引数1:引数2 }}
Intro of
this step
フィルタ1
フィルタ2
フィルタ3
表示出力
式
サンプル:orderBy で並べ替え
• ajs06_orderby.html
– orderBy フィルタで並べ替えする例
<!DOCTYPE html>
<html ng-app>
<head>
<meta charset="UTF-8" />
<title>サンプル06</title>
<script src="angular.min.js"></script>
</head>
<body ng-init="words = ['プリン','プリンタ','プロバイダ','プロフェッショナル','プール']">
<ul>
<li ng-repeat="word in words | orderBy : word : false">
{{word}}
</li>
</ul>
</body>
</html>
orderBy フィルタは集合の並べ替えを行う。
第1引数が並べ替え基準のプロパティ名(この場合は変数自体)
第2引数は降順にするかどうかの Bool 値 (true なら降順)
サンプル:フィルタによる絞り込み
• ajs07_filter.html
– 配列を filter フィルタで絞り込んだ結果を反復処理する例
<!DOCTYPE html>
<html ng-app>
<head>~</head>
<body ng-init="words = ['プリン','プリンタ','プロバイダ','プロフェッショナル','プール']">
<ul>
<li ng-repeat="word in words | filter:'プロ'">
{{word}}
</li>
</ul>
</body>
</html>
filter フィルタは、引数で指定された文字列を
含むものだけを抽出するフィルタ。
この例では、'プロ' という文字列が含まれるもの
だけが表示される。
サンプル:絞り込み条件をバインド
• ajs08_bindfilter.html
– データバインドした変数をフィルタの条件に指定する例
<!DOCTYPE html>
<html ng-app>
<head>~</head>
<body ng-init="words = ['プリン','プリンタ','プロバイダ','プロフェッショナル','プール']">
<input type="text" ng-model="name" />
<ul>
<li ng-repeat="word in words | filter:name">
{{word}}
</li>
</ul>
</body>
</html>
input 要素のボックスに入力された文字列に
データバインディングした name 変数を
フィルタの条件として引数に指定している。
input 要素の入力と name 変数は同期する
ので入力に応じて動的に一覧が絞り込まれる
ステップ3:ポイントまとめ
• フィルタとは
– 式の値を表示する書式を設定できるようにする機能
– 式の右側にパイプ記号(|)で区切って並べることで作用させる:
• {{ expression | filter }}
– 式 expression に filter を作用させる例
– フィルタの出力に別のフィルタを作用させることもできる:
• {{ expression | filter1 | filter2 }}
– 式 expression に filter1 を作用させた出力に filter2 を作用させる例
– フィルタは引数を受け取ることができる:
• {{ expression | filter:arg1:arg2・・・ }}
– 第1引数に arg1、第2引数に arg2 を受け取るフィルタの使用例
– フィルタの例
• filter フィルタ:引数に指定した文字列を含むものだけを抽出する
• orderBy フィルタ:引数に指定した項目に基づいて並べ替えを行う
ステップ4:コントローラとスコープ (1)
• AngularJS による UI
– 画面要素は拡張 HTML で記述する = テンプレート
– UI に関するロジックはどこに書く?
• コントローラ
– AngularJS の UI 関連ロジックを記述する場所
• コントローラ オブジェクトのコンストラクタとして定義する(後述)
• =MVC の Controller:View や Model と連携して処理を制御する部分
– コントローラは View(テンプレート)とどうやって連携するのか?
View Controller
テンプレート(HTML) JavaScript
ステップ4:コントローラとスコープ (2)
• スコープ:テンプレートとコントローラの仲介役
– コントローラのコンストラクタに引数 $scope として渡される
• テンプレートとコントローラの両方からアクセスできるオブジェクト
– コントローラ側:
$scope のプロパティとして変数や関数を設定する
– テンプレート (View) 側:
ng-controller ディレクティブで特定のコントローラを要素に指定すると、
そのコントローラに対応する $scope の各プロパティに、
単独のプロパティ名や関数名でアクセスできる。
View Controller$scope
テンプレート(HTML) JavaScript
スコープ
{{name}}
ng-click="myfunc()"
$scope.name = ・・・;
$scope.myfunc =
function() {・・・};
name myfunc
プロパティ / メソッド
サンプル:コントローラで配列を定義
• ajs09_controller.html
– ng-init ではなく、コントローラで配列を定義する例
<!DOCTYPE html>
<html ng-app="myapp">
<head>~</head>
<body ng-controller="MyController">
<input type="text" ng-model="name" />
<ul>
<li ng-repeat="word in words | filter:name">
{{word}}
</li>
</ul>
<script>
angular.module("myapp", [])
.controller("MyController", function ($scope) {
$scope.words = ['プリン', 'プリンタ', 'プロバイダ', 'プロフェッショナル', 'プール'];
});
</script>
</body>
</html>
angular.module() API でモジュール(後述)を作り、
その controller() メソッドにコントロール名とコンストラクタ
関数を渡してコントローラを定義する。
コントローラのスコープを有効にする範囲のルート要素に
ng-controller ディレクティブでコントローラ名を指定
サンプル:コントローラでメソッドを定義
• ajs10_ctrlmethod.html
– $scope に設定したメソッドをテンプレート側のクリックハンドラとして設定する例
<!DOCTYPE html>
<html ng-app="myapp">
<head>~</head>
<body ng-controller="MyController">
<button ng-click="myfunc()">呼び出しテスト</button>
<script>
angular.module("myapp", [])
.controller("MyController", function ($scope) {
$scope.myfunc = function () {
alert("myfunc: 呼び出されました");
};
});
</script>
</body>
</html>
ng-click ディレクティブで、クリックされたときの応答を設
定している。この例では myfunc() 関数が呼び出される。
コントローラ側では $scope のプロパティ
myfunc として関数を設定している。
サンプル:複数のコントローラを定義する
• ajs11_multictrl.html
– 2つのコントローラを登録して同じ名前で異なる実装の関数をスコープに設定する例
~
<body>
<div ng-controller="MyController1">
<button ng-click="myfunc()">呼び出しテスト1</button>
</div>
<div ng-controller="MyController2">
<button ng-click="myfunc()">呼び出しテスト2</button>
</div>
<script>
angular.module("myapp", [])
.controller("MyController1", function ($scope) {
$scope.myfunc = function () {
alert("myfunc: コントローラ1で呼び出されました");
};
})
.controller("MyController2", function ($scope) {
$scope.myfunc = function () {
alert("myfunc: コントローラ2で呼び出されました");
};
});
</script>
</body>
~
MyController1 のスコープで
myfunc を呼び出す
MyController2 のスコープで
myfunc を呼び出す
controller メソッドの戻り値が
元のモジュールになっているので、
ピリオド . で連結して繰り返し
呼び出すことができる
(メソッドチェーン)
ステップ4:まとめ
• コントローラ
– AngularJS の UI 関連ロジックを記述する場所
• モジュールの controller メソッドで登録する
– 第1引数:コントローラ名
– 第2引数:コンストラクタ関数を指定する
– テンプレート (HTML) とのデータ交換
• コンストラクタに渡される $scope という名前の引数を通じて行う
– テンプレートとコントローラの両方からアクセスできるオブジェクト
• 使い方
– コントローラ側
• テンプレートと共有する変数や関数を $scope 変数のプロパティとして設定する
– テンプレート側
• コントローラを関連づける範囲のルート要素に
ng-controller ディレクティブでコントローラの名前を指定する
– ng-controller ディレクティブがスコープの有効範囲を定義する
• そのコントローラの $scope のプロパティが、ルート配下で変数や関数としてアクセスできる
ステップ5:モジュールとサービス
• モジュールとは
– AngularJS アプリケーションの構成要素を束ねるコンテナ
• コントローラ、フィルタ、ディレクティブ、サービス・・・
– angular.module() API で作成する
• 第1引数:モジュール名
• 第2引数:依存する別のモジュール名の配列
– ng-app ディレクティブに指定することで有効になる
• アプリケーションのルート モジュールとなる
ディレクティブフィルタ サービス コントローラ ・・・
モジュール
前出のサンプルでモジュールの部分を確認
• ajs10_ctrlmethod.html
– myapp という名前でアプリケーションのルートモジュールを作成して初期化する例
<!DOCTYPE html>
<html ng-app="myapp">
<head>~</head>
<body ng-controller="MyController">
<button ng-click="myfunc()">呼び出しテスト</button>
<script>
angular.module("myapp", [])
.controller("MyController", function ($scope) {
$scope.myfunc = function () {
alert("myfunc: 呼び出されました");
};
});
</script>
</body>
</html>
第1引数:モジュールの名前
ここでは myapp という名前を指定
第2引数:依存先のモジュール名の配列
この例では依存モジュールはないので空の配列
ng-app ディレクティブに
アプリケーションのモジュール名を指定
サービスについて
• サービスとは
– アプリケーションの中で特定のタスクを担当するコンポーネント
• ライブラリで用意しているもの(例:$http サービス)
• 自作するもの
• 依存性注入(DI = Dependency Injection)
– あるオブジェクトが動作するのに必要なコンポーネントを外部から組み込む仕組み
– AngularJS は注入するサービスを引数の名前で決定する
• 例)$scope という名前を引数に指定するとスコープオブジェクトが自動的に渡される
– 変数名を変えるとスコープとして機能しなくなる
サービスの
コンポーネント
AngularJS がサービス コンポーネントのインスタンスを生成して注入する
生成注入
サンプル:$http サービスの利用
• $http サービスを利用して GET リクエストを発行する例
~
<body ng-controller="MyController">
<button ng-click="myfunc()">$httpテスト</button>
<input type="text" ng-model="result" />
<script>
angular.module('myapp', [])
.controller('MyController', function ($scope, $http) {
$scope.myfunc = function () {
$http({
method: 'GET', url: 'ajs12.txt'
})
.success(function (data, status, headers, config) {
$scope.result = data;
})
.error(function (data, status, headers, config) {
$scope.result = 'エラー';
});
};
});
</script>
</body>
~
ajs12_modhttp.html
この引数を通じて $http サービスの
インスタンスが注入される
テキストボックスの入力値と
$scope.result をデータバインド
ajs12.txt の内容が
読み込まれる
非同期通信:$http サービス (1)
• $http サービス
– XMLHttpRequest(XHR)オブジェクトのラッパー
– $http() 関数の呼び出しで非同期の HTTP リクエストを送信する
– この関数の返却値にコールバックを設定できる:
• then(<成功時コールバック>, <エラー時コールバック>)
– 成功時と失敗時の両方をまとめて指定する
• success(<コールバック関数>) メソッド
– 通信成功時(HTTP ステータス 200)に呼び出されるコールバック関数を指定する
• error(<コールバック関数>) メソッド
– 通信失敗時(ステータス 200以外)に呼び出されるコールバック関数を指定する
▼$http サービス
$http({パラメータ:値,パラメータ:値,・・・})
・パラメータ:非同期通信のパラメータ名
・値:パラメータに対応する指定値
非同期通信:$http サービス (2)
• $http の引数に渡すオブジェクトのパラメータ仕様
– https://docs.angularjs.org/api/ng/service/$http
• コールバック関数の引数
パラメータ名 説明
method 送信するリクエストの HTTP メソッド名を文字列で指定する
url リクエストの送信先 URL
params クエリパラメータのハッシュ形式(キー:値, ・・・)
data 送信するデータのハッシュ形式(キー:値, ・・・)
headers リクエスヘッダーのハッシュ形式(キー:値, ・・・)
パラメータ名 説明
data レスポンスの本文(JSONの場合は変換後のオブジェクト)
status HTTPステータスコード
headers レスポンスヘッダー
config リクエスト発行時に渡された構成オブジェクト
サービスの自作
• ビジネスロジックの分離
– ビジネスロジックは独立したサービス コンポーネントに分離する
– サービスを分離するメリット
• 一つのサービスを複数のコントローラで共有できる
• コントローラは制御に徹することができ見通しを立てやすい
• ビジネスロジック単体でのテストがしやすくなる
– モジュールのメソッドで定義する
• value(name, object)
– object: 文字列、数値、配列、オブジェクト、関数
• service(name, constructor)
– constructor: 共有するオブジェクトのコンストラクタ関数
• factory(name, func)
– func: 共有するオブジェクトを返却する関数
サンプル:value メソッドで値の共有
• value メソッドで共有文字列を指定する例
– ajs13_modvalue.html
~
<script>
angular.module("myapp", [])
.controller("MyController1", function ($scope, CommonValue) {
$scope.myfunc = function () {
alert("コントローラ1:" + CommonValue);
};
})
.controller("MyController2", function ($scope, CommonValue) {
$scope.myfunc = function () {
alert("コントローラ2:" + CommonValue);
};
})
.value('CommonValue', 'hogege');
</script>
</body>
</html>
この引数を通じて $http サービスの
インスタンスが注入される
第1引数に文字列として指定した名前で
第2引数の値(この例では文字列)をサービスとして登録する。
異なるコントローラから
同じ値を参照できる
サンプル:service メソッドで値の共有 (1)
• service メソッドで共有オブジェクトのコンストラクタを指定する例
– ajs14_modservice.html
<!DOCTYPE html>
<html ng-app="myapp">
<head>
<meta charset="UTF-8" />
<title>サンプル14</title>
<script src="angular.min.js"></script>
</head>
<body ng-controller="MyController">
<button ng-click="myfunc()">リクエスト送信</button>
<script>
angular.module("myapp", [])
.controller("MyController", function ($scope, MyModel) {
$scope.myfunc = function () {
MyModel.sendRequest();
};
})
~
MyModel サービスの
インスタンスが注入される
インスタンスのメソッドを呼び出す
サンプル:service メソッドで値の共有 (2)
<script>
angular.module("myapp", [])
.controller("MyController", function ($scope, MyModel) {
$scope.myfunc = function () {
MyModel.sendRequest();
};
})
.service('MyModel', function ($http) {
this.sendRequest = function () {
$http({
method: 'GET',
url: 'ajs12.txt'
})
.success(function (data, status, headers, config) {
alert("success: " + data);
})
.error(function (data, status, headers, config) {
alert("error: " + data);
});
};
});
</script>
~
service メソッドでは、第2引数に
サービスのコンストラクタ関数を指定する
service で作成するサービスでは、
$http 等の別のサービスを注入できる。
(value メソッドの場合は不可)
$http サービスを注入することで
通信処理をモデル側に移動している
サンプル:factory メソッドで書き換える
• factory メソッドで先の MyModel を書き換える例
– ajs15_modfactory.html
angular.module("myapp", [])
.controller("MyController", function ($scope, MyModel) {
$scope.myfunc = function () {
MyModel.sendRequest();
};
})
.factory('MyModel', function ($http) {
return {
sendRequest: function () {
$http({
method: 'GET',
url: 'ajs12.txt'
})
.success(function (data, status, headers, config) {
alert("success: " + data);
})
.error(function (data, status, headers, config) {
alert("error: " + data);
});
}
};
});
factory メソッドの場合は、
コンポーネントのコンストラクタではなく、
そのコンポーネントを返却する関数を指定する。
既存コンポーネントの場合は、
単にそのインスタンスを返却すればよい
(そのような場合に便利なメソッド)
ステップ5:まとめ
• モジュール
– AngularJS アプリケーションの構成要素を束ねるコンテナ
– angular.module() API で作成する
• 第1引数:モジュール名
• 第2引数:依存する別のモジュール名の配列
– ng-app ディレクティブにモジュール名を指定すると使用可能になる
• サービス
– 特定のビジネスロジックを独立したコンポーネントとして分離したもの
– サービス定義用のメソッドがモジュールに用意されている:
• value(name, object) シンプルな値に名前をつけてサービスとして共有
• service(name, constructor) 指定したコンストラクタで生成されるオブジェクトを共有
• factory(name, func) 指定した関数が返却するオブジェクトを共有
– 依存性注入(DI)
• サービスのコンポーネントのインスタンス生成と組み込みを自動的に行う仕組み
• 関数の引数名をサービス名にすることで対応するインスタンスが自動的に生成されて渡される
ステップ6:ルーティング
• ルーティングとは
– リクエストの URL に応じてコントローラとテンプレートを振り分けること
• 特定のパス(のパターン)と、コントローラ/テンプレートを関連づける
– これにより、遷移ページごとに異なるテンプレートとコントローラを指定できる
コントローラ コントローラ コントローラ
テンプレート テンプレート テンプレート
AngularJS アプリケーション
$routeProvider
URLパターン コントローラ テンプレート
/ MainController main.html
/about AboutController about.html
・・・
リクエスト
パスを指定する
$routeProvider が登録された対照表に基づき
リクエストを適切なコントローラ/テンプレートに割り振る
サンプル:ルーティングによるページ遷移 (1)
• ファイル構成(ajs16 フォルダ内)
– テンプレートファイル
• index.html アプリケーションの入り口となるファイル
• main.html 相対パス ~/ に対応する内容のテンプレート
• about.html 相対パス ~/about に対応する内容のテンプレート
• guide.html 相対パス ~/guide に対応する内容のテンプレート
– JavaScript ファイル
• myapp.js
– これまでテンプレート内に直接記述していたコードを別ファイルに分離
– angular.min.js と angular-route.min.js を先に読み込むことが前提
サンプル:ルーティングによるページ遷移 (2)
• index.html
<!DOCTYPE html>
<html ng-app="myapp">
<head>
<meta charset="UTF-8" />
<title>サンプル16</title>
</head>
<body>
<div class="header">
<a href="#/">Main</a> |
<a href="#/about">About</a> |
<a href="#/guide">Guide</a>
</div>
<hr/>
<div class="content" ng-view></div>
<hr/>
<div class="footer">サンプル16</div>
<script src="angular.min.js"></script>
<script src="angular-route.min.js"></script>
<script src="myapp.js"></script>
</body>
</html>
ng-view ディレクティブを指定した要素の配下に
パスに対応するコンテンツが埋め込まれる。
各遷移先の URL は、リンク元のページの
URL に # で区切ってパスを連結した形になる
サンプル:ルーティングによるページ遷移 (3)
• myapp.js
angular.module("myapp", ['ngRoute'])
.config(function ($routeProvider) {
$routeProvider
.when('/', { templateUrl: 'main.html', controller: 'MainController' })
.when('/about', { templateUrl: 'about.html', controller: 'AboutController' })
.when('/guide', { templateUrl: 'guide.html', controller: 'GuideController' })
.otherwise({
redirectTo: '/'
})
})
.controller('MainController', function ($scope) {
$scope.content = 'main のコンテンツ';
})
.controller('AboutController', function ($scope) {
$scope.content = 'about のコンテンツ';
})
.controller('GuideController', function ($scope) {
$scope.content = 'guide のコンテンツ';
});
$routeProvider の when メソッドを利用して
パスとコントローラ/テンプレートを対応付けしている。
第1引数:パス
第2引数:テンプレートとコントローラを指定する連想配列
otherwise メソッドは、いずれも該当しない場合の処理を定義する。
redirectTo は指定したパスにリダイレクトさせる指定。
ルーティング機能は AngularJS のコアではなく
ngRoute モジュールなので依存先に指定する
サンプル:ルーティングによるページ遷移 (4)
• ルーティング先のコンテンツ用テンプレート
<h1>メイン</h1>
<div>{{content}}</div>
<h1>このサイトについて</h1>
<div>{{content}}</div>
<h1>ガイド</h1>
<div>{{content}}</div>
main.html
about.html
guide.html
各ファイルとも AngularJS 式 {{content}} を出力している。
同じ記述でもコントローラが変わると出力も変わる。
ヘッダーとフッターの部分は index.html で共通。
ステップ6:まとめ
• ルーティングの設定
– ngRoute という非コアモジュールを利用する:
• angular-route.min.js ファイルをインポートし、
• モジュールの依存先モジュール(第2引数の配列)に 'ngRoute' を指定する
• $routeProvider を利用してパスとコントローラ/テンプレートを関連づける
– $routeProvider は DI で注入される
– 下記メソッドを利用してパスとコンテンツを関連づける
» when('<パス>', <連想配列>) パスごとの指定
» otherwise いずれのも該当しない場合の指定
• 連想配列の形式:{templateUrl:~, controller:~}
– config() メソッドで行う
• ルーティング設定はモジュールの config() メソッドに渡す関数の中で行う
– 出力先に ng-view ディレクティブ
• 各パスに対応するコンテンツは ng-view を指定した要素の下に出力される
ステップ7:フォーム
• AngularJS のフォーム拡張
– HTML のフォームやコンポーネントの要素も拡張が加えられている
– 拡張の例)
• form 要素の拡張属性
– name フォームの名前(検証で使用)
– ng-submit submit 時に呼び出す処理
– novalidate HTML5 の検証処理を無効化する
• input、textarea 要素の拡張属性(一部)
– ng-model 入力値とデータバインドする変数名
– name 要素の名前
– ng-change 入力値に変更があったときに呼び出す処理
– ng-required 必須かどうかを指定する
• select 要素の拡張属性
– ng-options 集合データからオプション要素を展開する
サンプル:select の使用例 (1)
• myapp_select.js
– コントローラ側で商品情報オブジェクトの配列をスコープにセットする
angular.module("myapp", [])
.controller('MyController', function ($scope) {
$scope.products = [
{ pid: 101, name: '鉛筆パック', price: 350 },
{ pid: 102, name: 'オフィスデスク', price: 35000 },
{ pid: 103, name: 'コピー用紙', price: 580 }
];
})
サンプル:select の使用例 (2)
• ajs17_select1.html
– 配列要素のオブジェクトの name プロパティをオプションとして表示する例
<!DOCTYPE html>
<html ng-app="myapp">
<head>
<meta charset="UTF-8" />
<title>サンプル17</title>
</head>
<body ng-controller="MyController">
<div>
<select id="pname" name="pname" ng-model="pname"
ng-options="prdct.name for prdct in products">
<option value="">(選択)</option>
</select>
</div>
<script src="angular.min.js"></script>
<script src="myapp_select.js"></script>
</body>
</html>
スコープ内の products 配列の要素を
prdct という変数で表して反復処理する例
for と in の使い方を確認してください。
別ファイルに分けたコントローラをインポート
サンプル:選択値を別個に指定する例
• ajs18_select2.html
– 選択値を表示値とは違うプロパティ(pid)に指定し、選択値を表示する例
<!DOCTYPE html>
<html ng-app="myapp">
<head>~</head>
<body ng-controller="MyController">
<div>
<select id="pname" name="pname" ng-model="selected"
ng-options="prdct.pid as prdct.name for prdct in products">
<option value="">(選択)</option>
</select>
<span>選択値:{{selected}}</span>
</div>
<script src="angular.min.js"></script>
<script src="myapp_select.js"></script>
</body>
</html>
スコープ内の products 配列の要素を
prdct という変数で表して反復処理する例
for と in の使い方を確認してください。
(参考)API とドキュメントについて
• AngularJS の API について
– AngularJSで提供される種々の機能の詳細は、
Webで公開されている API ドキュメント(英語)で調べることができる:
• https://docs.angularjs.org/api
• ドキュメント調査のヒント
– ディレクティブ
• テンプレート(HTMLファイル)で利用できるAngularJSの命令で、タグや属性として指定する。
• ディレクティブには複数の表記法がありいずれの異なる表記法で記述しても機能としては等価:
内部的には、先頭から「x-」「data-」を削除し、「:」「-」「_」で区切られた名前をキャメルケース
(camelCase)にすることで表記法を統一できる。ドキュメントではこの表記法が使われている。
• 各ディレクティブに説明とサンプルコードが提供されており、具体的な使い方を確認できる。
– フィルタ
• テンプレート上に埋め込まれたデータの書式を設定するための仕組み
– サービス
• アプリケーション開発に役立つ機能を提供する。
• 依存性注入を利用してサービスをインスタンス化して注入することで利用できる。
(参考)配列アノテーションによる DI
• ソース圧縮による引数名変更の問題
– ソース圧縮(ミニフィケーション)で引数名が変更される可能性がある
• $scope という引数名を目印にインジェクションが行われるため、
この名前が変更されるとコードが動作しなくなる
• 識別名 $scope の変更を防ぐには文字列として処理系に伝える方法が必要
• 対策:配列アノテーション
– 配列要素として、引数名の文字列と関数を指定する方法
• 従来の方法
.controller('CtrlName',function($scope){・・・});
• 配列アノテーション
.controller('CtrlName',['$scope',function($scope){・・・}]);
– DI に必要な引数名を文字列の配列要素として設定する
– 複数ある場合は引数の順に設定する
サンプル:ajs12_modhttpX.html
• $scope と $http の使用例に配列アノテーションを適用すると・・・
– ajs12_modhttpX.html
<script>
angular.module('myapp', [])
.controller('MyController',
['$scope', '$http', function($scope, $http) {
$scope.myfunc = function () {
$http({
method: 'GET',
url: 'ajs12.txt'
})
.success(function (data, status, headers, config) {
$scope.result = data;
})
.error(function (data, status, headers, config) {
$scope.result = 'エラー';
});
};
}]);
</script>
第1引数が $scope、第2引数が $http なので
この順番で次の配列を controller に渡している
['$scope', '$http', function(~)]
配列アノテーションを使用した場合、関数の引数名は変更しても
正しく動作するが、可読性のために変更せずそのままにしている。

Más contenido relacionado

La actualidad más candente

Typescript Fundamentals
Typescript FundamentalsTypescript Fundamentals
Typescript FundamentalsSunny Sharma
 
AWS設計ガイドラインで取り組むクラウドシフト
AWS設計ガイドラインで取り組むクラウドシフトAWS設計ガイドラインで取り組むクラウドシフト
AWS設計ガイドラインで取り組むクラウドシフトTrainocate Japan, Ltd.
 
Riverpodでテストを書こう
Riverpodでテストを書こうRiverpodでテストを書こう
Riverpodでテストを書こうShinnosuke Tokuda
 
社内Java8勉強会 ラムダ式とストリームAPI
社内Java8勉強会 ラムダ式とストリームAPI社内Java8勉強会 ラムダ式とストリームAPI
社内Java8勉強会 ラムダ式とストリームAPIAkihiro Ikezoe
 
Swaggerでのapi開発よもやま話
Swaggerでのapi開発よもやま話Swaggerでのapi開発よもやま話
Swaggerでのapi開発よもやま話KEISUKE KONISHI
 
Integration Testing with a Citrus twist
Integration Testing with a Citrus twistIntegration Testing with a Citrus twist
Integration Testing with a Citrus twistchristophd
 
Spring Day 2016 - Web API アクセス制御の最適解
Spring Day 2016 - Web API アクセス制御の最適解Spring Day 2016 - Web API アクセス制御の最適解
Spring Day 2016 - Web API アクセス制御の最適解都元ダイスケ Miyamoto
 
nioで作ったBufferedWriterに変えたら例外になった
nioで作ったBufferedWriterに変えたら例外になったnioで作ったBufferedWriterに変えたら例外になった
nioで作ったBufferedWriterに変えたら例外になったchibochibo
 
PHP 8 で Web 以外の世界の扉を叩く
PHP 8 で Web 以外の世界の扉を叩くPHP 8 で Web 以外の世界の扉を叩く
PHP 8 で Web 以外の世界の扉を叩くshinjiigarashi
 
Amazon Cognito使って認証したい?それならSpring Security使いましょう!
Amazon Cognito使って認証したい?それならSpring Security使いましょう!Amazon Cognito使って認証したい?それならSpring Security使いましょう!
Amazon Cognito使って認証したい?それならSpring Security使いましょう!Ryosuke Uchitate
 
KeycloakでFAPIに対応した高セキュリティなAPIを公開する
KeycloakでFAPIに対応した高セキュリティなAPIを公開するKeycloakでFAPIに対応した高セキュリティなAPIを公開する
KeycloakでFAPIに対応した高セキュリティなAPIを公開するHitachi, Ltd. OSS Solution Center.
 
Open source APM Scouter로 모니터링 잘 하기
Open source APM Scouter로 모니터링 잘 하기Open source APM Scouter로 모니터링 잘 하기
Open source APM Scouter로 모니터링 잘 하기GunHee Lee
 
ASP.NET MVC と jQuery で実践する標準志向 Web 開発
ASP.NET MVC と jQuery で実践する標準志向 Web 開発ASP.NET MVC と jQuery で実践する標準志向 Web 開発
ASP.NET MVC と jQuery で実践する標準志向 Web 開発Akira Inoue
 
Introduzione ad angular 7/8
Introduzione ad angular 7/8Introduzione ad angular 7/8
Introduzione ad angular 7/8Valerio Radice
 
Java null survival guide
Java null survival guideJava null survival guide
Java null survival guideSungchul Park
 
T119_5年間の試行錯誤で進化したMVPVMパターン
T119_5年間の試行錯誤で進化したMVPVMパターンT119_5年間の試行錯誤で進化したMVPVMパターン
T119_5年間の試行錯誤で進化したMVPVMパターン伸男 伊藤
 
Spring Fest 2017 「エンタープライズで利用するSpring Boot」#jsug #sf_h1
Spring Fest 2017 「エンタープライズで利用するSpring Boot」#jsug #sf_h1Spring Fest 2017 「エンタープライズで利用するSpring Boot」#jsug #sf_h1
Spring Fest 2017 「エンタープライズで利用するSpring Boot」#jsug #sf_h1Takeshi Hirosue
 

La actualidad más candente (20)

Typescript Fundamentals
Typescript FundamentalsTypescript Fundamentals
Typescript Fundamentals
 
AWS設計ガイドラインで取り組むクラウドシフト
AWS設計ガイドラインで取り組むクラウドシフトAWS設計ガイドラインで取り組むクラウドシフト
AWS設計ガイドラインで取り組むクラウドシフト
 
Riverpodでテストを書こう
Riverpodでテストを書こうRiverpodでテストを書こう
Riverpodでテストを書こう
 
社内Java8勉強会 ラムダ式とストリームAPI
社内Java8勉強会 ラムダ式とストリームAPI社内Java8勉強会 ラムダ式とストリームAPI
社内Java8勉強会 ラムダ式とストリームAPI
 
Swaggerでのapi開発よもやま話
Swaggerでのapi開発よもやま話Swaggerでのapi開発よもやま話
Swaggerでのapi開発よもやま話
 
Storage and Alfresco
Storage and AlfrescoStorage and Alfresco
Storage and Alfresco
 
Integration Testing with a Citrus twist
Integration Testing with a Citrus twistIntegration Testing with a Citrus twist
Integration Testing with a Citrus twist
 
Spring Day 2016 - Web API アクセス制御の最適解
Spring Day 2016 - Web API アクセス制御の最適解Spring Day 2016 - Web API アクセス制御の最適解
Spring Day 2016 - Web API アクセス制御の最適解
 
nioで作ったBufferedWriterに変えたら例外になった
nioで作ったBufferedWriterに変えたら例外になったnioで作ったBufferedWriterに変えたら例外になった
nioで作ったBufferedWriterに変えたら例外になった
 
PHP 8 で Web 以外の世界の扉を叩く
PHP 8 で Web 以外の世界の扉を叩くPHP 8 で Web 以外の世界の扉を叩く
PHP 8 で Web 以外の世界の扉を叩く
 
Angular
AngularAngular
Angular
 
Amazon Cognito使って認証したい?それならSpring Security使いましょう!
Amazon Cognito使って認証したい?それならSpring Security使いましょう!Amazon Cognito使って認証したい?それならSpring Security使いましょう!
Amazon Cognito使って認証したい?それならSpring Security使いましょう!
 
KeycloakでFAPIに対応した高セキュリティなAPIを公開する
KeycloakでFAPIに対応した高セキュリティなAPIを公開するKeycloakでFAPIに対応した高セキュリティなAPIを公開する
KeycloakでFAPIに対応した高セキュリティなAPIを公開する
 
Open source APM Scouter로 모니터링 잘 하기
Open source APM Scouter로 모니터링 잘 하기Open source APM Scouter로 모니터링 잘 하기
Open source APM Scouter로 모니터링 잘 하기
 
ASP.NET MVC と jQuery で実践する標準志向 Web 開発
ASP.NET MVC と jQuery で実践する標準志向 Web 開発ASP.NET MVC と jQuery で実践する標準志向 Web 開発
ASP.NET MVC と jQuery で実践する標準志向 Web 開発
 
Introduzione ad angular 7/8
Introduzione ad angular 7/8Introduzione ad angular 7/8
Introduzione ad angular 7/8
 
An introduction to Vue.js
An introduction to Vue.jsAn introduction to Vue.js
An introduction to Vue.js
 
Java null survival guide
Java null survival guideJava null survival guide
Java null survival guide
 
T119_5年間の試行錯誤で進化したMVPVMパターン
T119_5年間の試行錯誤で進化したMVPVMパターンT119_5年間の試行錯誤で進化したMVPVMパターン
T119_5年間の試行錯誤で進化したMVPVMパターン
 
Spring Fest 2017 「エンタープライズで利用するSpring Boot」#jsug #sf_h1
Spring Fest 2017 「エンタープライズで利用するSpring Boot」#jsug #sf_h1Spring Fest 2017 「エンタープライズで利用するSpring Boot」#jsug #sf_h1
Spring Fest 2017 「エンタープライズで利用するSpring Boot」#jsug #sf_h1
 

Similar a AngularJS入門

JavaScriptテンプレートエンジンで活かすData API
JavaScriptテンプレートエンジンで活かすData APIJavaScriptテンプレートエンジンで活かすData API
JavaScriptテンプレートエンジンで活かすData APIHajime Fujimoto
 
エンタープライズ分野での実践AngularJS
エンタープライズ分野での実践AngularJSエンタープライズ分野での実践AngularJS
エンタープライズ分野での実践AngularJSAyumi Goto
 
HTML5 ビギナーのための AngularJS
HTML5 ビギナーのための AngularJSHTML5 ビギナーのための AngularJS
HTML5 ビギナーのための AngularJSKenichi Kanai
 
ASP.NET MVC 2 ~新機能の紹介~
ASP.NET MVC 2 ~新機能の紹介~ASP.NET MVC 2 ~新機能の紹介~
ASP.NET MVC 2 ~新機能の紹介~Yoshitaka Seo
 
AngularJSを触ってみた
AngularJSを触ってみたAngularJSを触ってみた
AngularJSを触ってみたtomowata
 
PHP 2大 web フレームワークの徹底比較!
PHP 2大 web フレームワークの徹底比較!PHP 2大 web フレームワークの徹底比較!
PHP 2大 web フレームワークの徹底比較!Shohei Okada
 
はじめての ASP.NET MVC
はじめての ASP.NET MVCはじめての ASP.NET MVC
はじめての ASP.NET MVCjz5 MATSUE
 
Parse.comと始めるBackbone.js入門(jscafe7)
Parse.comと始めるBackbone.js入門(jscafe7)Parse.comと始めるBackbone.js入門(jscafe7)
Parse.comと始めるBackbone.js入門(jscafe7)Ryuma Tsukano
 
Pro aspnetmvc3framework chap15
Pro aspnetmvc3framework chap15Pro aspnetmvc3framework chap15
Pro aspnetmvc3framework chap15Hideki Hashizume
 
XPagesDay2014 A-4 XPages with jQueryMobile BADプラクティスガイド
XPagesDay2014 A-4 XPages with jQueryMobile BADプラクティスガイドXPagesDay2014 A-4 XPages with jQueryMobile BADプラクティスガイド
XPagesDay2014 A-4 XPages with jQueryMobile BADプラクティスガイドTetsuji Hayashi
 
Cocoa Pro5
Cocoa Pro5Cocoa Pro5
Cocoa Pro5hasegawa
 
scala+liftで遊ぼう
scala+liftで遊ぼうscala+liftで遊ぼう
scala+liftで遊ぼうyouku
 
Magento meet up Tokyo#1 for Design
Magento meet up Tokyo#1 for DesignMagento meet up Tokyo#1 for Design
Magento meet up Tokyo#1 for DesignMiho Nakano
 
jQuery と MVC で実践する標準志向 Web 開発
jQuery と MVC で実践する標準志向 Web 開発jQuery と MVC で実践する標準志向 Web 開発
jQuery と MVC で実践する標準志向 Web 開発Akira Inoue
 
Angular2 rc.1 unit testing overview
Angular2 rc.1 unit testing overviewAngular2 rc.1 unit testing overview
Angular2 rc.1 unit testing overviewMitsuru Ogawa
 
基礎から見直す ASP.NET MVC の単体テスト自動化方法 ~ Windows Azure 関連もあるかも~
基礎から見直す ASP.NET MVC の単体テスト自動化方法 ~ Windows Azure 関連もあるかも~基礎から見直す ASP.NET MVC の単体テスト自動化方法 ~ Windows Azure 関連もあるかも~
基礎から見直す ASP.NET MVC の単体テスト自動化方法 ~ Windows Azure 関連もあるかも~normalian
 
OSC2014.Enterprise Zabbix-JobScheduler連携ツールHyClopsJobMonitoringによる運用システムOSS化の実現
OSC2014.Enterprise Zabbix-JobScheduler連携ツールHyClopsJobMonitoringによる運用システムOSS化の実現OSC2014.Enterprise Zabbix-JobScheduler連携ツールHyClopsJobMonitoringによる運用システムOSS化の実現
OSC2014.Enterprise Zabbix-JobScheduler連携ツールHyClopsJobMonitoringによる運用システムOSS化の実現Daisuke Ikeda
 
はじめてのCodeIgniter
はじめてのCodeIgniterはじめてのCodeIgniter
はじめてのCodeIgniterYuya Matsushima
 

Similar a AngularJS入門 (20)

JavaScriptテンプレートエンジンで活かすData API
JavaScriptテンプレートエンジンで活かすData APIJavaScriptテンプレートエンジンで活かすData API
JavaScriptテンプレートエンジンで活かすData API
 
エンタープライズ分野での実践AngularJS
エンタープライズ分野での実践AngularJSエンタープライズ分野での実践AngularJS
エンタープライズ分野での実践AngularJS
 
HTML5 ビギナーのための AngularJS
HTML5 ビギナーのための AngularJSHTML5 ビギナーのための AngularJS
HTML5 ビギナーのための AngularJS
 
ASP.NET MVC 2 ~新機能の紹介~
ASP.NET MVC 2 ~新機能の紹介~ASP.NET MVC 2 ~新機能の紹介~
ASP.NET MVC 2 ~新機能の紹介~
 
AngularJSを触ってみた
AngularJSを触ってみたAngularJSを触ってみた
AngularJSを触ってみた
 
PHP 2大 web フレームワークの徹底比較!
PHP 2大 web フレームワークの徹底比較!PHP 2大 web フレームワークの徹底比較!
PHP 2大 web フレームワークの徹底比較!
 
はじめての ASP.NET MVC
はじめての ASP.NET MVCはじめての ASP.NET MVC
はじめての ASP.NET MVC
 
Parse.comと始めるBackbone.js入門(jscafe7)
Parse.comと始めるBackbone.js入門(jscafe7)Parse.comと始めるBackbone.js入門(jscafe7)
Parse.comと始めるBackbone.js入門(jscafe7)
 
Pro aspnetmvc3framework chap15
Pro aspnetmvc3framework chap15Pro aspnetmvc3framework chap15
Pro aspnetmvc3framework chap15
 
Vue入門
Vue入門Vue入門
Vue入門
 
XPagesDay2014 A-4 XPages with jQueryMobile BADプラクティスガイド
XPagesDay2014 A-4 XPages with jQueryMobile BADプラクティスガイドXPagesDay2014 A-4 XPages with jQueryMobile BADプラクティスガイド
XPagesDay2014 A-4 XPages with jQueryMobile BADプラクティスガイド
 
Cocoa Pro5
Cocoa Pro5Cocoa Pro5
Cocoa Pro5
 
scala+liftで遊ぼう
scala+liftで遊ぼうscala+liftで遊ぼう
scala+liftで遊ぼう
 
ASP.NET MVC 1.0
ASP.NET MVC 1.0ASP.NET MVC 1.0
ASP.NET MVC 1.0
 
Magento meet up Tokyo#1 for Design
Magento meet up Tokyo#1 for DesignMagento meet up Tokyo#1 for Design
Magento meet up Tokyo#1 for Design
 
jQuery と MVC で実践する標準志向 Web 開発
jQuery と MVC で実践する標準志向 Web 開発jQuery と MVC で実践する標準志向 Web 開発
jQuery と MVC で実践する標準志向 Web 開発
 
Angular2 rc.1 unit testing overview
Angular2 rc.1 unit testing overviewAngular2 rc.1 unit testing overview
Angular2 rc.1 unit testing overview
 
基礎から見直す ASP.NET MVC の単体テスト自動化方法 ~ Windows Azure 関連もあるかも~
基礎から見直す ASP.NET MVC の単体テスト自動化方法 ~ Windows Azure 関連もあるかも~基礎から見直す ASP.NET MVC の単体テスト自動化方法 ~ Windows Azure 関連もあるかも~
基礎から見直す ASP.NET MVC の単体テスト自動化方法 ~ Windows Azure 関連もあるかも~
 
OSC2014.Enterprise Zabbix-JobScheduler連携ツールHyClopsJobMonitoringによる運用システムOSS化の実現
OSC2014.Enterprise Zabbix-JobScheduler連携ツールHyClopsJobMonitoringによる運用システムOSS化の実現OSC2014.Enterprise Zabbix-JobScheduler連携ツールHyClopsJobMonitoringによる運用システムOSS化の実現
OSC2014.Enterprise Zabbix-JobScheduler連携ツールHyClopsJobMonitoringによる運用システムOSS化の実現
 
はじめてのCodeIgniter
はじめてのCodeIgniterはじめてのCodeIgniter
はじめてのCodeIgniter
 

Más de Kenji Shirane

Drupal、group、quiz、webformを利用したeラーニングサイト「sqt」
Drupal、group、quiz、webformを利用したeラーニングサイト「sqt」Drupal、group、quiz、webformを利用したeラーニングサイト「sqt」
Drupal、group、quiz、webformを利用したeラーニングサイト「sqt」Kenji Shirane
 
D8でコンテンツをレイアウトする手法について
D8でコンテンツをレイアウトする手法についてD8でコンテンツをレイアウトする手法について
D8でコンテンツをレイアウトする手法についてKenji Shirane
 
CMSMix Sapporo vol.3 (Drupal の回)
CMSMix Sapporo vol.3 (Drupal の回)CMSMix Sapporo vol.3 (Drupal の回)
CMSMix Sapporo vol.3 (Drupal の回)Kenji Shirane
 
Drupal のコア要素を知る ~構築を支える道具立て~
Drupal のコア要素を知る ~構築を支える道具立て~Drupal のコア要素を知る ~構築を支える道具立て~
Drupal のコア要素を知る ~構築を支える道具立て~Kenji Shirane
 
Drupal 7 の多言語機能について
Drupal 7 の多言語機能についてDrupal 7 の多言語機能について
Drupal 7 の多言語機能についてKenji Shirane
 
Drupalテーマとthemingの基礎
Drupalテーマとthemingの基礎Drupalテーマとthemingの基礎
Drupalテーマとthemingの基礎Kenji Shirane
 
Drupal勉強会@さっぽろ/おたる ご紹介
Drupal勉強会@さっぽろ/おたる ご紹介Drupal勉強会@さっぽろ/おたる ご紹介
Drupal勉強会@さっぽろ/おたる ご紹介Kenji Shirane
 

Más de Kenji Shirane (7)

Drupal、group、quiz、webformを利用したeラーニングサイト「sqt」
Drupal、group、quiz、webformを利用したeラーニングサイト「sqt」Drupal、group、quiz、webformを利用したeラーニングサイト「sqt」
Drupal、group、quiz、webformを利用したeラーニングサイト「sqt」
 
D8でコンテンツをレイアウトする手法について
D8でコンテンツをレイアウトする手法についてD8でコンテンツをレイアウトする手法について
D8でコンテンツをレイアウトする手法について
 
CMSMix Sapporo vol.3 (Drupal の回)
CMSMix Sapporo vol.3 (Drupal の回)CMSMix Sapporo vol.3 (Drupal の回)
CMSMix Sapporo vol.3 (Drupal の回)
 
Drupal のコア要素を知る ~構築を支える道具立て~
Drupal のコア要素を知る ~構築を支える道具立て~Drupal のコア要素を知る ~構築を支える道具立て~
Drupal のコア要素を知る ~構築を支える道具立て~
 
Drupal 7 の多言語機能について
Drupal 7 の多言語機能についてDrupal 7 の多言語機能について
Drupal 7 の多言語機能について
 
Drupalテーマとthemingの基礎
Drupalテーマとthemingの基礎Drupalテーマとthemingの基礎
Drupalテーマとthemingの基礎
 
Drupal勉強会@さっぽろ/おたる ご紹介
Drupal勉強会@さっぽろ/おたる ご紹介Drupal勉強会@さっぽろ/おたる ご紹介
Drupal勉強会@さっぽろ/おたる ご紹介
 

AngularJS入門

  • 3. Obserever パターンと UI 設計 • Observer パターン – Observer: Subject の変更を監視し、変更時に表示を更新する – Subject: データを保持し、Observer の登録・削除メソッドを持つ • Model-View – UI 設計に Observer パターンを適用 • 表示機能(View)と表示対象データ(Model)とに分割し、 • 0 個以上の View が Model を observe する構造で UI を構成する view1 modelview2 view3 Observer Subject +notify() +notifyObserves() +addObserver() +deleteObserver() * ①Model を操作 (データの変更発生) ②Model は変更したことを View に通知する ③View は Model から変更後のデータを取得して表示更新
  • 4. MVC パターン • MVC パターン – Model(ビジネスロジック)、View(ユーザーインターフェイス)、 Controller(Model と View の仲立ち)の3つの責務に基づいて アプリケーションを構成する設計パターン 要素 責務(役割) Model(モデル) アプリケーションが扱うデータの管理と操作を受け持つ。 データを操作するための機能(ビジネスロジック)を提供する。 View(ビュー) ユーザーインターフェイスに対応する部分。 ユーザーからの入力受付と結果の表示を担当する。 Controller(コントローラ) Model と View の両方に関連を持ち、処理の流れを制御す る役割を受け持つ。View から受け取ったデータを Model に 渡し、表示の更新が必要な Model の変更を View に通知 する。
  • 5. (参考)Model2(MVC2) • Model2 – MVC をサーブレット/JSP 等の Web システム構造に適用したもの • JSP 仕様のドラフトにおいて提唱された(1998年) – 実質的な UI であるブラウザにモデルの変更が通知される仕組みはない (Observer パターンになっていない) Controller View Model転送 操作 参照 ブラウザ 要求 応答
  • 6. Model-View-Controller View Conroller Model ユーザー操作 呼び出し 操作 変更通知 Observer パターンの Subject Observer パターンの Observer Model の変更を View に 通知して表示を更新させる Observer パターンの構造が基本。 Model の変更を View に通知する 仕組みを実装する必要がある。
  • 7. MVVM:Model-View-ViewModel • MVVM:MVC の派生パターン – View • ユーザーからの入出力操作を 受け付ける UI – ViewModel • 表示用の状態データ – View と同期(データバインディング) • View からの入力を Model に反映させる役割 – Model • アプリケーション固有の部分 – ビジネスロジック – データ View ViewModel Model ユーザー操作 データバインディング ユーザー インターフェイス 表示用データ ビジネスロジック データ 操作 取得
  • 8. JavaScript MVC/MVVM フレームワーク • AngularJS – フルスタックの JavaScript MVC フレームワーク • React – Facebook によるフレームーワーク。View の機能を提供する。 • Backbone.js – シンプルな構造が特徴のフレームワーク。 • Knockout.js – ASP.NET SPA アプリに標準対応したフレームワーク • Ember.js – フルスタックのフレームワーク
  • 9. AngularJS とは • AngularJS とは – JavaScript によるアプリケーション フレームワーク – MVC に基づくクライアントアプリケーション開発をサポート – 入手先 • https://angularjs.org/ • 特徴 – Google を中心に開発されている – ドキュメント/関連ライブラリの充実 – フルスタック • MVC 構造のほか アプリ開発に必要な種々の機能
  • 10. AngularJS を使用するには • script タグの href 属性に指定してインポート – CDN 経由 – コピーを取得 • ダウンロード • Bower で取得 • npm で取得
  • 12. AngularJS の中核機能 • テンプレート – ディレクティブ – AngularJS 式 – データバインディング • View-ViewModel – 反復表示 • ng-repeat – フィルタ • MVC – Controller – テンプレートとの関連付け – サービス • ビジネスロジックの分離 – 依存性注入 • Dependency Injection – ルーティング
  • 13. ステップ1:テンプレートとディレクティブ • テンプレート – MVC の View となるページを記述する • HTML の拡張構文を利用する • AngularJS の HTML 構文拡張 – AngularJS 式: {{ <式> }} • AngularJS の処理系が式を評価し、その結果に変換される – ディレクティブ • DOM 要素(属性、HTML タグ名、コメント、CSS クラス)のマーカー • 指定した DOM 要素に特定の振る舞いを関連付ける働きを持つ • 双方向データバインディング – テンプレートの要素と表示用データを相互に同期させる仕組み • MVVM における View と ViewModel の関係 Intro of this step
  • 14. サンプル:テンプレート HTML • ajs00_template.html – テンプレート出発点:AngularJS 適用前の普通の HTML <!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <title>サンプル00</title> </head> <body> <h1>3 + 4</h1> </body> </html>
  • 15. サンプル:AngularJS 式 • ajs01_expression.html – AngularJS 式で 「3+4」 を評価させる例 <!DOCTYPE html> <html ng-app> <head> <meta charset="UTF-8" /> <title>サンプル01</title> <script src="angular.min.js"></script> </head> <body> <h1>{{3 + 4}}</h1> </body> </html> ng-app ディレクティブ AngularJS を初期化し、処理対象のルート要素を指定する AngularJS 式:{{ ~ }} AngularJS による評価結果が表示される式
  • 16. サンプル:双方向データバインディング • ajs02_databinding.html – 双方向バインディングの例 • ng-model ディレクティブを指定した input 要素と変数 name との間で データバインディングをする例 <!DOCTYPE html> <html ng-app> <head>~</head> <body> 名前: <input type="text" ng-model="name" /> {{name}} </body> </html> ng-model ディレクティブ input、select、textarea の各要素を 変数(=スコープのプロパティ:後述)にバインドする。 変数が存在しない場合は新たに定義される。 ng-model でバインドした変数の評価式: input タグの入力値が自動的に反映される。 name 変数が変更されると逆に input 要素が更新される
  • 17. ステップ1:ポイントまとめ • テンプレート – 拡張版の HTML でテンプレートを記述する • AngularJS がテンプレートを読み込んで処理した結果が表示される • AngularJS 式:{{ }} – {{ と }} で囲んで記述した式のこと • 式を評価した結果が表示される • ディレクティブ – DOM 要素に特定の振る舞いを関連付けるマーカー • ng-app ディレクティブ – AngularJS の初期化と処理対象のルート要素を指定する • ng-model ディレクティブ – input、select、textarea の各要素と変数をバインドして相互に値を同期させる
  • 18. ステップ2:反復表示 • ng-repeat ディレクティブ – コレクションを全件処理する • 配列の要素 • オブジェクトのプロパティ • ng-init ディレクティブ – 代入式などの式を現在のスコープ内で評価(実行)する • スコープ内の変数の初期化に用いられる Intro of this step
  • 19. サンプル:配列の反復処理 • ajs03_repeat1.html – 配列を反復処理して要素を全件表示する例 <!DOCTYPE html> <html ng-app> <head>~</head> <body> <ul> <li ng-repeat="item in ['太郎', '次郎', 'ぜんじろう']"> 項目{{$index}} = {{item}} </li> </ul> </body> </html> 「変数 in 配列」 の 形式で属性に指定 ng-repeat ディレクティブ この属性を含む要素(li)を反復出力する $index 予約変数 反復処理の中で各要素の インデックスが設定される
  • 20. サンプル:オブジェクトのプロパティの読み出し • ajs04_repeat2.html – オブジェクトのプロパティを順次読み出す例 <!DOCTYPE html> <html ng-app> <head>~</head> <body> <ul> <li ng-repeat="(k,v) in {name:'太郎',age:25}"> {{k}}の値 = {{v}} </li> </ul> </body> </html> オブジェクトのリテラル 1番目の変数(この例では k):プロパティ名 2番目の変数(この例では v):プロパティの値 AngularJS 式で変数を参照
  • 21. サンプル:in の後を変数に置換 • ajs05_repeat3.html – in の後にリテラルではなく変数を配置する例 <!DOCTYPE html> <html ng-app> <head>~</head> <body ng-init="obj={name:'太郎',age:25,address:'札幌'}"> <ul> <li ng-repeat="(k, v) in obj"> {{k}}の値 = {{v}} </li> </ul> </body> </html> 変数 obj へのオブジェクトリテラルの代入式を ng-init ディレクティブで評価(実行)する 上記の代入式で初期化された変数 obj を 反復処理の対象オブジェクトとして指定している
  • 22. ステップ2:ポイントまとめ • ng-repeat ディレクティブ – 配列の要素を順次取得して反復処理を行う • 例)<div ng-repeat="member in group">~</div> – group:集合 – member:集合の要素が順次代入される変数 – オブジェクトのプロパティを順次取得して反復処理を行う • 例)<div ng-repeat="(key, value) in object">~</div> – key:オブジェクトのプロパティ名 – value:プロパティの値 – objcet:プロパティを取り出す対象のオブジェクト ※1)いずれも ~ の部分で {{ }} 式を用いて要素やプロパティの値を出力できる ※2)特別に予約された変数 $index で処理中の要素のインデックスを取得できる • ng-init ディレクティブ – 代入式などの式を現在のスコープ内で評価(実行)する
  • 23. ステップ3:フィルタ • フィルタとは – 式の値を通過させることで、 • 書式の設定 • 値の変換 • 条件に該当しないものの除外 • 並べ替え ・・・ など変更を加えた結果を取得する機能 – 表記法 • パイプ記号(|)で作用させる – {{ 式 | フィルタ1 | フィルタ2 | フィルタ3 }} • コロン (:) でフィルタに引数を渡すこともできる – {{ 式 | フィルタ:引数1:引数2 }} Intro of this step フィルタ1 フィルタ2 フィルタ3 表示出力 式
  • 24. サンプル:orderBy で並べ替え • ajs06_orderby.html – orderBy フィルタで並べ替えする例 <!DOCTYPE html> <html ng-app> <head> <meta charset="UTF-8" /> <title>サンプル06</title> <script src="angular.min.js"></script> </head> <body ng-init="words = ['プリン','プリンタ','プロバイダ','プロフェッショナル','プール']"> <ul> <li ng-repeat="word in words | orderBy : word : false"> {{word}} </li> </ul> </body> </html> orderBy フィルタは集合の並べ替えを行う。 第1引数が並べ替え基準のプロパティ名(この場合は変数自体) 第2引数は降順にするかどうかの Bool 値 (true なら降順)
  • 25. サンプル:フィルタによる絞り込み • ajs07_filter.html – 配列を filter フィルタで絞り込んだ結果を反復処理する例 <!DOCTYPE html> <html ng-app> <head>~</head> <body ng-init="words = ['プリン','プリンタ','プロバイダ','プロフェッショナル','プール']"> <ul> <li ng-repeat="word in words | filter:'プロ'"> {{word}} </li> </ul> </body> </html> filter フィルタは、引数で指定された文字列を 含むものだけを抽出するフィルタ。 この例では、'プロ' という文字列が含まれるもの だけが表示される。
  • 26. サンプル:絞り込み条件をバインド • ajs08_bindfilter.html – データバインドした変数をフィルタの条件に指定する例 <!DOCTYPE html> <html ng-app> <head>~</head> <body ng-init="words = ['プリン','プリンタ','プロバイダ','プロフェッショナル','プール']"> <input type="text" ng-model="name" /> <ul> <li ng-repeat="word in words | filter:name"> {{word}} </li> </ul> </body> </html> input 要素のボックスに入力された文字列に データバインディングした name 変数を フィルタの条件として引数に指定している。 input 要素の入力と name 変数は同期する ので入力に応じて動的に一覧が絞り込まれる
  • 27. ステップ3:ポイントまとめ • フィルタとは – 式の値を表示する書式を設定できるようにする機能 – 式の右側にパイプ記号(|)で区切って並べることで作用させる: • {{ expression | filter }} – 式 expression に filter を作用させる例 – フィルタの出力に別のフィルタを作用させることもできる: • {{ expression | filter1 | filter2 }} – 式 expression に filter1 を作用させた出力に filter2 を作用させる例 – フィルタは引数を受け取ることができる: • {{ expression | filter:arg1:arg2・・・ }} – 第1引数に arg1、第2引数に arg2 を受け取るフィルタの使用例 – フィルタの例 • filter フィルタ:引数に指定した文字列を含むものだけを抽出する • orderBy フィルタ:引数に指定した項目に基づいて並べ替えを行う
  • 28. ステップ4:コントローラとスコープ (1) • AngularJS による UI – 画面要素は拡張 HTML で記述する = テンプレート – UI に関するロジックはどこに書く? • コントローラ – AngularJS の UI 関連ロジックを記述する場所 • コントローラ オブジェクトのコンストラクタとして定義する(後述) • =MVC の Controller:View や Model と連携して処理を制御する部分 – コントローラは View(テンプレート)とどうやって連携するのか? View Controller テンプレート(HTML) JavaScript
  • 29. ステップ4:コントローラとスコープ (2) • スコープ:テンプレートとコントローラの仲介役 – コントローラのコンストラクタに引数 $scope として渡される • テンプレートとコントローラの両方からアクセスできるオブジェクト – コントローラ側: $scope のプロパティとして変数や関数を設定する – テンプレート (View) 側: ng-controller ディレクティブで特定のコントローラを要素に指定すると、 そのコントローラに対応する $scope の各プロパティに、 単独のプロパティ名や関数名でアクセスできる。 View Controller$scope テンプレート(HTML) JavaScript スコープ {{name}} ng-click="myfunc()" $scope.name = ・・・; $scope.myfunc = function() {・・・}; name myfunc プロパティ / メソッド
  • 30. サンプル:コントローラで配列を定義 • ajs09_controller.html – ng-init ではなく、コントローラで配列を定義する例 <!DOCTYPE html> <html ng-app="myapp"> <head>~</head> <body ng-controller="MyController"> <input type="text" ng-model="name" /> <ul> <li ng-repeat="word in words | filter:name"> {{word}} </li> </ul> <script> angular.module("myapp", []) .controller("MyController", function ($scope) { $scope.words = ['プリン', 'プリンタ', 'プロバイダ', 'プロフェッショナル', 'プール']; }); </script> </body> </html> angular.module() API でモジュール(後述)を作り、 その controller() メソッドにコントロール名とコンストラクタ 関数を渡してコントローラを定義する。 コントローラのスコープを有効にする範囲のルート要素に ng-controller ディレクティブでコントローラ名を指定
  • 31. サンプル:コントローラでメソッドを定義 • ajs10_ctrlmethod.html – $scope に設定したメソッドをテンプレート側のクリックハンドラとして設定する例 <!DOCTYPE html> <html ng-app="myapp"> <head>~</head> <body ng-controller="MyController"> <button ng-click="myfunc()">呼び出しテスト</button> <script> angular.module("myapp", []) .controller("MyController", function ($scope) { $scope.myfunc = function () { alert("myfunc: 呼び出されました"); }; }); </script> </body> </html> ng-click ディレクティブで、クリックされたときの応答を設 定している。この例では myfunc() 関数が呼び出される。 コントローラ側では $scope のプロパティ myfunc として関数を設定している。
  • 32. サンプル:複数のコントローラを定義する • ajs11_multictrl.html – 2つのコントローラを登録して同じ名前で異なる実装の関数をスコープに設定する例 ~ <body> <div ng-controller="MyController1"> <button ng-click="myfunc()">呼び出しテスト1</button> </div> <div ng-controller="MyController2"> <button ng-click="myfunc()">呼び出しテスト2</button> </div> <script> angular.module("myapp", []) .controller("MyController1", function ($scope) { $scope.myfunc = function () { alert("myfunc: コントローラ1で呼び出されました"); }; }) .controller("MyController2", function ($scope) { $scope.myfunc = function () { alert("myfunc: コントローラ2で呼び出されました"); }; }); </script> </body> ~ MyController1 のスコープで myfunc を呼び出す MyController2 のスコープで myfunc を呼び出す controller メソッドの戻り値が 元のモジュールになっているので、 ピリオド . で連結して繰り返し 呼び出すことができる (メソッドチェーン)
  • 33. ステップ4:まとめ • コントローラ – AngularJS の UI 関連ロジックを記述する場所 • モジュールの controller メソッドで登録する – 第1引数:コントローラ名 – 第2引数:コンストラクタ関数を指定する – テンプレート (HTML) とのデータ交換 • コンストラクタに渡される $scope という名前の引数を通じて行う – テンプレートとコントローラの両方からアクセスできるオブジェクト • 使い方 – コントローラ側 • テンプレートと共有する変数や関数を $scope 変数のプロパティとして設定する – テンプレート側 • コントローラを関連づける範囲のルート要素に ng-controller ディレクティブでコントローラの名前を指定する – ng-controller ディレクティブがスコープの有効範囲を定義する • そのコントローラの $scope のプロパティが、ルート配下で変数や関数としてアクセスできる
  • 34. ステップ5:モジュールとサービス • モジュールとは – AngularJS アプリケーションの構成要素を束ねるコンテナ • コントローラ、フィルタ、ディレクティブ、サービス・・・ – angular.module() API で作成する • 第1引数:モジュール名 • 第2引数:依存する別のモジュール名の配列 – ng-app ディレクティブに指定することで有効になる • アプリケーションのルート モジュールとなる ディレクティブフィルタ サービス コントローラ ・・・ モジュール
  • 35. 前出のサンプルでモジュールの部分を確認 • ajs10_ctrlmethod.html – myapp という名前でアプリケーションのルートモジュールを作成して初期化する例 <!DOCTYPE html> <html ng-app="myapp"> <head>~</head> <body ng-controller="MyController"> <button ng-click="myfunc()">呼び出しテスト</button> <script> angular.module("myapp", []) .controller("MyController", function ($scope) { $scope.myfunc = function () { alert("myfunc: 呼び出されました"); }; }); </script> </body> </html> 第1引数:モジュールの名前 ここでは myapp という名前を指定 第2引数:依存先のモジュール名の配列 この例では依存モジュールはないので空の配列 ng-app ディレクティブに アプリケーションのモジュール名を指定
  • 36. サービスについて • サービスとは – アプリケーションの中で特定のタスクを担当するコンポーネント • ライブラリで用意しているもの(例:$http サービス) • 自作するもの • 依存性注入(DI = Dependency Injection) – あるオブジェクトが動作するのに必要なコンポーネントを外部から組み込む仕組み – AngularJS は注入するサービスを引数の名前で決定する • 例)$scope という名前を引数に指定するとスコープオブジェクトが自動的に渡される – 変数名を変えるとスコープとして機能しなくなる サービスの コンポーネント AngularJS がサービス コンポーネントのインスタンスを生成して注入する 生成注入
  • 37. サンプル:$http サービスの利用 • $http サービスを利用して GET リクエストを発行する例 ~ <body ng-controller="MyController"> <button ng-click="myfunc()">$httpテスト</button> <input type="text" ng-model="result" /> <script> angular.module('myapp', []) .controller('MyController', function ($scope, $http) { $scope.myfunc = function () { $http({ method: 'GET', url: 'ajs12.txt' }) .success(function (data, status, headers, config) { $scope.result = data; }) .error(function (data, status, headers, config) { $scope.result = 'エラー'; }); }; }); </script> </body> ~ ajs12_modhttp.html この引数を通じて $http サービスの インスタンスが注入される テキストボックスの入力値と $scope.result をデータバインド ajs12.txt の内容が 読み込まれる
  • 38. 非同期通信:$http サービス (1) • $http サービス – XMLHttpRequest(XHR)オブジェクトのラッパー – $http() 関数の呼び出しで非同期の HTTP リクエストを送信する – この関数の返却値にコールバックを設定できる: • then(<成功時コールバック>, <エラー時コールバック>) – 成功時と失敗時の両方をまとめて指定する • success(<コールバック関数>) メソッド – 通信成功時(HTTP ステータス 200)に呼び出されるコールバック関数を指定する • error(<コールバック関数>) メソッド – 通信失敗時(ステータス 200以外)に呼び出されるコールバック関数を指定する ▼$http サービス $http({パラメータ:値,パラメータ:値,・・・}) ・パラメータ:非同期通信のパラメータ名 ・値:パラメータに対応する指定値
  • 39. 非同期通信:$http サービス (2) • $http の引数に渡すオブジェクトのパラメータ仕様 – https://docs.angularjs.org/api/ng/service/$http • コールバック関数の引数 パラメータ名 説明 method 送信するリクエストの HTTP メソッド名を文字列で指定する url リクエストの送信先 URL params クエリパラメータのハッシュ形式(キー:値, ・・・) data 送信するデータのハッシュ形式(キー:値, ・・・) headers リクエスヘッダーのハッシュ形式(キー:値, ・・・) パラメータ名 説明 data レスポンスの本文(JSONの場合は変換後のオブジェクト) status HTTPステータスコード headers レスポンスヘッダー config リクエスト発行時に渡された構成オブジェクト
  • 40. サービスの自作 • ビジネスロジックの分離 – ビジネスロジックは独立したサービス コンポーネントに分離する – サービスを分離するメリット • 一つのサービスを複数のコントローラで共有できる • コントローラは制御に徹することができ見通しを立てやすい • ビジネスロジック単体でのテストがしやすくなる – モジュールのメソッドで定義する • value(name, object) – object: 文字列、数値、配列、オブジェクト、関数 • service(name, constructor) – constructor: 共有するオブジェクトのコンストラクタ関数 • factory(name, func) – func: 共有するオブジェクトを返却する関数
  • 41. サンプル:value メソッドで値の共有 • value メソッドで共有文字列を指定する例 – ajs13_modvalue.html ~ <script> angular.module("myapp", []) .controller("MyController1", function ($scope, CommonValue) { $scope.myfunc = function () { alert("コントローラ1:" + CommonValue); }; }) .controller("MyController2", function ($scope, CommonValue) { $scope.myfunc = function () { alert("コントローラ2:" + CommonValue); }; }) .value('CommonValue', 'hogege'); </script> </body> </html> この引数を通じて $http サービスの インスタンスが注入される 第1引数に文字列として指定した名前で 第2引数の値(この例では文字列)をサービスとして登録する。 異なるコントローラから 同じ値を参照できる
  • 42. サンプル:service メソッドで値の共有 (1) • service メソッドで共有オブジェクトのコンストラクタを指定する例 – ajs14_modservice.html <!DOCTYPE html> <html ng-app="myapp"> <head> <meta charset="UTF-8" /> <title>サンプル14</title> <script src="angular.min.js"></script> </head> <body ng-controller="MyController"> <button ng-click="myfunc()">リクエスト送信</button> <script> angular.module("myapp", []) .controller("MyController", function ($scope, MyModel) { $scope.myfunc = function () { MyModel.sendRequest(); }; }) ~ MyModel サービスの インスタンスが注入される インスタンスのメソッドを呼び出す
  • 43. サンプル:service メソッドで値の共有 (2) <script> angular.module("myapp", []) .controller("MyController", function ($scope, MyModel) { $scope.myfunc = function () { MyModel.sendRequest(); }; }) .service('MyModel', function ($http) { this.sendRequest = function () { $http({ method: 'GET', url: 'ajs12.txt' }) .success(function (data, status, headers, config) { alert("success: " + data); }) .error(function (data, status, headers, config) { alert("error: " + data); }); }; }); </script> ~ service メソッドでは、第2引数に サービスのコンストラクタ関数を指定する service で作成するサービスでは、 $http 等の別のサービスを注入できる。 (value メソッドの場合は不可) $http サービスを注入することで 通信処理をモデル側に移動している
  • 44. サンプル:factory メソッドで書き換える • factory メソッドで先の MyModel を書き換える例 – ajs15_modfactory.html angular.module("myapp", []) .controller("MyController", function ($scope, MyModel) { $scope.myfunc = function () { MyModel.sendRequest(); }; }) .factory('MyModel', function ($http) { return { sendRequest: function () { $http({ method: 'GET', url: 'ajs12.txt' }) .success(function (data, status, headers, config) { alert("success: " + data); }) .error(function (data, status, headers, config) { alert("error: " + data); }); } }; }); factory メソッドの場合は、 コンポーネントのコンストラクタではなく、 そのコンポーネントを返却する関数を指定する。 既存コンポーネントの場合は、 単にそのインスタンスを返却すればよい (そのような場合に便利なメソッド)
  • 45. ステップ5:まとめ • モジュール – AngularJS アプリケーションの構成要素を束ねるコンテナ – angular.module() API で作成する • 第1引数:モジュール名 • 第2引数:依存する別のモジュール名の配列 – ng-app ディレクティブにモジュール名を指定すると使用可能になる • サービス – 特定のビジネスロジックを独立したコンポーネントとして分離したもの – サービス定義用のメソッドがモジュールに用意されている: • value(name, object) シンプルな値に名前をつけてサービスとして共有 • service(name, constructor) 指定したコンストラクタで生成されるオブジェクトを共有 • factory(name, func) 指定した関数が返却するオブジェクトを共有 – 依存性注入(DI) • サービスのコンポーネントのインスタンス生成と組み込みを自動的に行う仕組み • 関数の引数名をサービス名にすることで対応するインスタンスが自動的に生成されて渡される
  • 46. ステップ6:ルーティング • ルーティングとは – リクエストの URL に応じてコントローラとテンプレートを振り分けること • 特定のパス(のパターン)と、コントローラ/テンプレートを関連づける – これにより、遷移ページごとに異なるテンプレートとコントローラを指定できる コントローラ コントローラ コントローラ テンプレート テンプレート テンプレート AngularJS アプリケーション $routeProvider URLパターン コントローラ テンプレート / MainController main.html /about AboutController about.html ・・・ リクエスト パスを指定する $routeProvider が登録された対照表に基づき リクエストを適切なコントローラ/テンプレートに割り振る
  • 47. サンプル:ルーティングによるページ遷移 (1) • ファイル構成(ajs16 フォルダ内) – テンプレートファイル • index.html アプリケーションの入り口となるファイル • main.html 相対パス ~/ に対応する内容のテンプレート • about.html 相対パス ~/about に対応する内容のテンプレート • guide.html 相対パス ~/guide に対応する内容のテンプレート – JavaScript ファイル • myapp.js – これまでテンプレート内に直接記述していたコードを別ファイルに分離 – angular.min.js と angular-route.min.js を先に読み込むことが前提
  • 48. サンプル:ルーティングによるページ遷移 (2) • index.html <!DOCTYPE html> <html ng-app="myapp"> <head> <meta charset="UTF-8" /> <title>サンプル16</title> </head> <body> <div class="header"> <a href="#/">Main</a> | <a href="#/about">About</a> | <a href="#/guide">Guide</a> </div> <hr/> <div class="content" ng-view></div> <hr/> <div class="footer">サンプル16</div> <script src="angular.min.js"></script> <script src="angular-route.min.js"></script> <script src="myapp.js"></script> </body> </html> ng-view ディレクティブを指定した要素の配下に パスに対応するコンテンツが埋め込まれる。 各遷移先の URL は、リンク元のページの URL に # で区切ってパスを連結した形になる
  • 49. サンプル:ルーティングによるページ遷移 (3) • myapp.js angular.module("myapp", ['ngRoute']) .config(function ($routeProvider) { $routeProvider .when('/', { templateUrl: 'main.html', controller: 'MainController' }) .when('/about', { templateUrl: 'about.html', controller: 'AboutController' }) .when('/guide', { templateUrl: 'guide.html', controller: 'GuideController' }) .otherwise({ redirectTo: '/' }) }) .controller('MainController', function ($scope) { $scope.content = 'main のコンテンツ'; }) .controller('AboutController', function ($scope) { $scope.content = 'about のコンテンツ'; }) .controller('GuideController', function ($scope) { $scope.content = 'guide のコンテンツ'; }); $routeProvider の when メソッドを利用して パスとコントローラ/テンプレートを対応付けしている。 第1引数:パス 第2引数:テンプレートとコントローラを指定する連想配列 otherwise メソッドは、いずれも該当しない場合の処理を定義する。 redirectTo は指定したパスにリダイレクトさせる指定。 ルーティング機能は AngularJS のコアではなく ngRoute モジュールなので依存先に指定する
  • 51. ステップ6:まとめ • ルーティングの設定 – ngRoute という非コアモジュールを利用する: • angular-route.min.js ファイルをインポートし、 • モジュールの依存先モジュール(第2引数の配列)に 'ngRoute' を指定する • $routeProvider を利用してパスとコントローラ/テンプレートを関連づける – $routeProvider は DI で注入される – 下記メソッドを利用してパスとコンテンツを関連づける » when('<パス>', <連想配列>) パスごとの指定 » otherwise いずれのも該当しない場合の指定 • 連想配列の形式:{templateUrl:~, controller:~} – config() メソッドで行う • ルーティング設定はモジュールの config() メソッドに渡す関数の中で行う – 出力先に ng-view ディレクティブ • 各パスに対応するコンテンツは ng-view を指定した要素の下に出力される
  • 52. ステップ7:フォーム • AngularJS のフォーム拡張 – HTML のフォームやコンポーネントの要素も拡張が加えられている – 拡張の例) • form 要素の拡張属性 – name フォームの名前(検証で使用) – ng-submit submit 時に呼び出す処理 – novalidate HTML5 の検証処理を無効化する • input、textarea 要素の拡張属性(一部) – ng-model 入力値とデータバインドする変数名 – name 要素の名前 – ng-change 入力値に変更があったときに呼び出す処理 – ng-required 必須かどうかを指定する • select 要素の拡張属性 – ng-options 集合データからオプション要素を展開する
  • 53. サンプル:select の使用例 (1) • myapp_select.js – コントローラ側で商品情報オブジェクトの配列をスコープにセットする angular.module("myapp", []) .controller('MyController', function ($scope) { $scope.products = [ { pid: 101, name: '鉛筆パック', price: 350 }, { pid: 102, name: 'オフィスデスク', price: 35000 }, { pid: 103, name: 'コピー用紙', price: 580 } ]; })
  • 54. サンプル:select の使用例 (2) • ajs17_select1.html – 配列要素のオブジェクトの name プロパティをオプションとして表示する例 <!DOCTYPE html> <html ng-app="myapp"> <head> <meta charset="UTF-8" /> <title>サンプル17</title> </head> <body ng-controller="MyController"> <div> <select id="pname" name="pname" ng-model="pname" ng-options="prdct.name for prdct in products"> <option value="">(選択)</option> </select> </div> <script src="angular.min.js"></script> <script src="myapp_select.js"></script> </body> </html> スコープ内の products 配列の要素を prdct という変数で表して反復処理する例 for と in の使い方を確認してください。 別ファイルに分けたコントローラをインポート
  • 55. サンプル:選択値を別個に指定する例 • ajs18_select2.html – 選択値を表示値とは違うプロパティ(pid)に指定し、選択値を表示する例 <!DOCTYPE html> <html ng-app="myapp"> <head>~</head> <body ng-controller="MyController"> <div> <select id="pname" name="pname" ng-model="selected" ng-options="prdct.pid as prdct.name for prdct in products"> <option value="">(選択)</option> </select> <span>選択値:{{selected}}</span> </div> <script src="angular.min.js"></script> <script src="myapp_select.js"></script> </body> </html> スコープ内の products 配列の要素を prdct という変数で表して反復処理する例 for と in の使い方を確認してください。
  • 56. (参考)API とドキュメントについて • AngularJS の API について – AngularJSで提供される種々の機能の詳細は、 Webで公開されている API ドキュメント(英語)で調べることができる: • https://docs.angularjs.org/api • ドキュメント調査のヒント – ディレクティブ • テンプレート(HTMLファイル)で利用できるAngularJSの命令で、タグや属性として指定する。 • ディレクティブには複数の表記法がありいずれの異なる表記法で記述しても機能としては等価: 内部的には、先頭から「x-」「data-」を削除し、「:」「-」「_」で区切られた名前をキャメルケース (camelCase)にすることで表記法を統一できる。ドキュメントではこの表記法が使われている。 • 各ディレクティブに説明とサンプルコードが提供されており、具体的な使い方を確認できる。 – フィルタ • テンプレート上に埋め込まれたデータの書式を設定するための仕組み – サービス • アプリケーション開発に役立つ機能を提供する。 • 依存性注入を利用してサービスをインスタンス化して注入することで利用できる。
  • 57. (参考)配列アノテーションによる DI • ソース圧縮による引数名変更の問題 – ソース圧縮(ミニフィケーション)で引数名が変更される可能性がある • $scope という引数名を目印にインジェクションが行われるため、 この名前が変更されるとコードが動作しなくなる • 識別名 $scope の変更を防ぐには文字列として処理系に伝える方法が必要 • 対策:配列アノテーション – 配列要素として、引数名の文字列と関数を指定する方法 • 従来の方法 .controller('CtrlName',function($scope){・・・}); • 配列アノテーション .controller('CtrlName',['$scope',function($scope){・・・}]); – DI に必要な引数名を文字列の配列要素として設定する – 複数ある場合は引数の順に設定する
  • 58. サンプル:ajs12_modhttpX.html • $scope と $http の使用例に配列アノテーションを適用すると・・・ – ajs12_modhttpX.html <script> angular.module('myapp', []) .controller('MyController', ['$scope', '$http', function($scope, $http) { $scope.myfunc = function () { $http({ method: 'GET', url: 'ajs12.txt' }) .success(function (data, status, headers, config) { $scope.result = data; }) .error(function (data, status, headers, config) { $scope.result = 'エラー'; }); }; }]); </script> 第1引数が $scope、第2引数が $http なので この順番で次の配列を controller に渡している ['$scope', '$http', function(~)] 配列アノテーションを使用した場合、関数の引数名は変更しても 正しく動作するが、可読性のために変更せずそのままにしている。