AngularJSの強力なデータバインディングの肝となる! スコープを理解して、独特な開発スタイルを自分のものにしよう

CodeZine / 2014年12月22日 14時0分

図4:AngularJSのイベント

 本連載は、JavaScriptのMVCフレームワークである、AngularJSを使った開発の解説記事です。前回に引き続き、AngularJSを使ってタスク管理をする1つのサンプルアプリケーションを通じて、その構造の理解や開発の流れなどを紹介します。今回は、コントローラ間のデータ連携を中心に説明します。

■はじめに

 前回に引き続き、AngularJSを使ってのタスク管理をするサンプルを作成していきます。前回まではタスク一覧ページを中心に実装し、ページを遷移するところまで実装しました。ただし、画面の遷移について、フッタのメニューを使っての遷移はできましたが、データと連携した画面遷移や、ボタンなどのクリックアクションを通じての画面遷移はしませんでした。今回はコントローラ間のデータ連携を中心に説明し、実際のサンプルでは、図1のようにクリックアクションからの画面遷移や、データの変更時のイベントを通知するための実装を行っていきます。

図1:今回作成するサンプルアプリの概要


■対象読者

jQueryなどを使っている開発者 JavaScriptを使った複数人でのプロジェクトに参加している方 JavaScriptを使ってサーバ等と連携したフロントエンドの開発をしている方 ■必要な環境

 この記事では、AngularJSを使用し、Chrome(36.0)、IE11、Firefox(31.0)、Safari(7.0.5)の環境にて確認を行っています。

■スコープ($scope)とは

 AngularJSでは、$scopeというオブジェクトを使用しテンプレートと連携をして、テンプレート内に記述した変数の設定やメソッドの起動などを行います。このように、$scopeは、モデル(プロパティ)の監視や、テンプレートのUIとその振る舞いを管理しています。たとえば、今回扱うサンプルコードでのHTMLテンプレートとコントローラ(スコープ)は、図2のような関係となります。

図2:HTMLとコントローラの関係


 またこれ以外にも、$scopeはコントーラ間のデータ連携などにも使えます。今回はそのデータ連係の機能を使ってサンプルコードを実装していきます。

■コントローラとスコープの関係

 AngularJSで$scope(以下、概念として説明する場合には「スコープ」と記します)を管理しているのは、ディレクティブです。

 ディレクティブを定義する際には、親スコープをそのまま共有するか、新たにスコープを作成するかなどの指定ができます。コントローラであるngControllerディレクティブでは、新規にスコープを作成するように定義されています。ただし、コントローラで作成されたスコープは、テンプレート上のディレクティブの親子関係を引き継いで利用する事ができます(=子コントローラのスコープは親コントローラのスコープから継承したインスタンスです)。具体的には図3のような関係を持っていて、この関係を用いて各コントローラのスコープを連携することができます。

図3:AngularJSでの$scopeの概要


表1:スコープのアクセス方法 変数名 説明 $scope.$parent 現在のスコープの親スコープへのアクセス $scope.$root $rootScopeへのアクセス これらのスコープの機能を利用したものがリスト1です。

 前回作成したページの表示・非表示を行うchangePageメソッド(1)がpageControllerにあります。

 (2)と(4)では、一覧表示からリストをクリックした際に呼ばれるshowメソッドとデータを登録した際に呼ばれるaddItemメソッドがありますが、これらの処理の完了後にページを遷移するために親スコープのメソッドであるchangePageメソッドを呼んでいます。

 (3)では、$scope.$rootで全体のスコープに対してアクセスしています。実際に呼んでいる$broadcastメソッドについては「スコープのイベント」にて説明します。

リスト1:controllers.jsの抜粋
module.controller('pageController',function($scope){ // (1) pageControllerのスコープにあるメソッド $scope.changePage = function(type){ // : 省略 }; }); // (2) pageControllerのchangePageメソッドを呼ぶ module.controller('listController',function($scope){ $scope.show = function(item){ // : 省略 $scope.$parent.changePage('info'); }; }); module.controller('addController',function($scope){ $scope.addItem = function(){ // : 省略 // (3) $rootScopeの$broadcastメソッドを呼ぶ $scope.$root.$broadcast('changeItems'); // (4) pageControllerのchangePageメソッドを呼ぶ $scope.$parent.changePage('list'); } });


CodeZine

トピックスRSS

ランキング