ウェブデザイナーがはじめる AngularJS シリーズウェブデザイナーがはじめるAngularJS:AngularUI Routerの基礎知識
はじめに
前回のウェブデザイナーがはじめるAngularJS:ngRouteを使ったシンプルなViewの切り替えでngRouteを使いました。今回はより高機能なAngularUI Routerを使ってみます。今回はngRouteでやったことと同じことをAngularUI Routerでやってみたいと思います。
AugularUI Routerとは
AngularUI Routerとは、ngRouteと同じルーティングモジュールのひとつ。ngRouteはURLを元にルーティングしていましたが、AngularUI Routerは状態(State)を元にルーティングを行います。State/Viewの入れ子ができ、複数のViewを作れるのが特徴です。
AngularUI Routerインストール
$ bower install angular-ui-router --save-dev
bower angular-ui-router#*   not-cached git://github.com/angular-ui/ui-router.git#*
bower angular-ui-router#*      resolve git://github.com/angular-ui/ui-router.git#*
bower angular-ui-router#*     download https://github.com/angular-ui/ui-router/archive/0.2.13.tar.gz
bower angular-ui-router#*      extract archive.tar.gz
bower angular-ui-router#*     resolved git://github.com/angular-ui/ui-router.git#0.2.13
bower angular-ui-router#~0.2.13          install angular-ui-router#0.2.13
angular-ui-router#0.2.13 vendor/bower_components/angular-ui-router
└── angular#1.3.15
 SprocketsにPathを通す
########################
#
# Sprockets setting
#
########################
after_configuration do
  sprockets.append_path '../vendor/bower_components'
  sprockets.append_path '../vendor/bower_components/angular'
  sprockets.append_path '../vendor/bower_components/angular-route'
  sprockets.append_path '../vendor/bower_components/angular-ui-router/release'
end
 ngRouteをAngularUI Routerに置き換える
前回の記事で作成したサンプルをAngularUI Routerに置き換えてみます。同じことをするだけであればほとんど作りは変わりません。
テンプレート
Viewとなるテンプレートに変更はありません。AngularUI Routerに対応させるためにindex.html.erbとscript.jsに手を加えます。
index.html.erb
まずリンクを指定しているng-hrefディレクティブがui-srefに代わり、valueが状態の名前home, loginになります。合わせてng-viewディレクティブをui-viewに変更します。
<nav class="c-nav">
  <ul class="nav-list">
    <li class="list-item"><a ui-sref="home">Home</a></li>
    <li class="list-item"><a ui-sref="login">Login</a></li>
  </ul>
</nav>
<section class="c-section">
  <div ui-view>
    ...
  </div>
</section>
 script.js
ModuleとRouterの定義のみ下記のように変更します。
// Moduleの定義
var example = angular.module('example', ['ui.router']); // 依存Moduleをui.routerに変更
// Routerの定義
example
  .config(['$stateProvider', '$urlRouterProvider', 
          function( stateProvider, urlRouterProvider ){
            urlRouterProvider.otherwise('/'); // .otherwise({ redirectTo: '/'});
            stateProvider
              .state('home', { // 状態の名前を定義する
                url: "/", // URL
                templateUrl: 'views/home.html' // テンプレート
              })
              .state('login', {
                url: "/login",
                templateUrl: 'views/login.html',
                controller: 'LoginCtrl' // コントローラ
              });
          }
        ]);
 これでngRouteと同じことが実現できます。
AngularUI Routerでできること
AngularUI Routerはシンプルなルーティングはもちろん、細かなカスタマイズができます。
Template
テンプレートはテンプレートファイルだけではなく、シンプルにStringを定義することもできます。
// in app-states.js (or whatever you want to name it)
$stateProvider.state('contacts', {
  template: '<h1>My Contacts</h1>'
})
  Controller
コントローラはモジュールを指定せずに、直接スコープを定義して使うこともできます。 (テンプレートが定義されていない場合コントローラがインスタンス化されません)
$stateProvider.state('contacts', {
  template: '<h1>{{title}}</h1>',
  controller: function($scope){
    $scope.title = 'My Contacts';
  }
})
  Custom Data to State Objects
Stateに対してカスタムデータを付与する仕組みがあります。
// Example shows an object-based state and a string-based state
$stateProvider
  .state('login', {
    templateUrl: 'views/login.html',
    data: {
        customData1: 10,
        customData2: "red"
    } 
  })
function Ctrl($state){
    console.log($state.current.data.customData1) // outputs 10;
    console.log($state.current.data.customData2) // outputs "red";
}
 Lean More: Attach Custom Data to State Objects
State Change Events / View Load Events
Stateが変わった時、Viewがロードされた時にイベントを発火させます。
- $stateChangeStart
 - $stateNotFound
 - $stateChangeSuccess
 - $stateChangeError
 - $viewContentLoading
 - $viewContentLoaded
 
$rootScope.$on('$stateChangeStart', 
function(event, toState, toParams, fromState, fromParams){ ... })
 Lean More: State Change Events
Nested States and Nested Views
StateやViewを入れ子にすることができます。
$stateProvider
  .state('login', {})
  .state('login.error', {});
 この書き方は一例で色々な書き方があるので、詳しくは下記を読んでみてください。
Lean More: Nested States and Nested Views
Multiple Named Views
複数のViewに対してStateを同時に設定することができます。
<!-- index.html -->
<body>
  <div ui-view="header"></div>
  <div ui-view="sidebar"></div>
  <div ui-view="contents"></div>
</body>
$stateProvider
  .state('home', {
    views: {
      'header': { ... templates and/or controllers ... },
      'sidebar': {},
      'contents': {},
    }
  })
 Lean More: Multiple Named Views
URL Routing
ルーティングの基本的な部分はngRouteと似ていますが、パラメータの値を正規表現で制限したりクリエパラメータに対応しています。
終わりに
かなり細かな制御が可能なRouterであることがよく分かりました。全体像をぱっと確認したい方は以下のガイドがお勧めです。
次回:ウェブデザイナーがはじめるAngularJS:ngCookiesやngStorageを使ったCookieやlocalStorageへのアクセス
シリーズ
- AngularJSをはじめる前に - AngularJSに関するサイトやスライドまとめ
 - ウェブデザイナーがはじめるAngularJS:AngularJSをはじめる
 - ウェブデザイナーがはじめるAngularJS:SPA(Single Page Application)をはじめる前に
 - ウェブデザイナーがはじめるAngularJS:MiddlemanとBowerで作るAngularJSアプリ開発環境
 - ウェブデザイナーがはじめるAngularJS:ngRouteを使ったシンプルなViewの切り替え
 - ウェブデザイナーがはじめるAngularJS:AngularUI Routerの基礎知識
 - ウェブデザイナーがはじめるAngularJS:ngCookiesやngStorageを使ったCookieやlocalStorageへのアクセス
 - ウェブデザイナーがはじめるAngularJS:DOM操作系ディレクティブを試す
 - ウェブデザイナーがはじめるAngularJS:イベント系ディレクティブを試す
 - ウェブデザイナーがはじめるAngularJS:Promise(Deferred)をつかった非同期処理
 - ウェブデザイナーがはじめるAngularJS:$httpProviderのInterceptorsを使ってリクエスト・レスポンスを操作する
 - ウェブデザイナーがはじめるAngularJS:Middlemanでng-annotateを使ったMinify対策
 - ウェブデザイナーがはじめるAngularJS:コントローラ間の連携
 - ウェブデザイナーがはじめるAngularJS:AngularJS向けのディレクティブが用意されたUI Bootstrap