SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

AngularJSではじめるJavaScriptフレームワーク開発スタイル

AngularJSのngRouteを使ってシングルページアプリケーション(SPA)を作ってみよう

AngularJSで初めるJavaScriptフレームワーク開発スタイル 第13回

  • X ポスト
  • このエントリーをはてなブックマークに追加

パスの指定とパスの遷移

 パスの指定方法ですが、パスには完全一致以外にもパラメータを含めて記述ができます。例えば、今回のサンプルではリスト5のように:(コロン)+変数名で各タスクの識別用IDをパスに含めるようにしています。

リスト5 パスの指定方法
$routeProvider.when('/item/:uid',{
  // (省略)
}

 これ以外にも表2のような記述ができます。詳しい説明はAPIリファレンスを参照してください。

表2 指定できるURLパターン
パターン 説明
:name /item/:name /item/book のように必ずnameに相当する値が必要。
:name? /item/:name? /itemもしくは/item/bookのいずれも一致。nameの指定が必ずしもいらない
:name* /category/:name* /category/book/hobby のように/category/以下の一致するような指定が可能

 パラメータで指定した変数は、リスト6のように$routeParamsサービスを利用して取得できます。

リスト6 $routeParamsによるパラメータ取得(ItemController.jsの抜粋)
module.controller('ItemController',[
    '$scope','$routeParams','$location','Items',     // (1) $routeParamsサービスを利用する
    function($scope,$routeParams,$location,Items){

        var uid = $routeParams['uid'];               // (2) パスからパラメータの取得  /item/35 の場合には uid = "35"となる
        $scope.item = Items.get(uid);
        // (省略)
    }]);

 (1)では、$routeParamsサービスをコントローラのDI機能を使って取得します。URLで指定したuidの値は取得した$routeParamsの配列形式として取得できます。

 続いて、ここで指定したパスへの遷移は$locationサービスのpathメソッドを用いて遷移します。リスト7はタスクを登録が完了したら、一覧ページに遷移する場合の利用例です。

リスト7 $location.pathメソッドを利用した画面遷移(AddController.jsの抜粋)
module.controller('AddController',['$scope','$location','Items','defaults',
    function($scope,$location,Items,defaults){
        // (省略)
        $scope.addItem = function(){
            if($scope.addItemForm.$valid) {
                Items.add($scope.item);
                $location.path("/list");   // pathを指定して画面遷移
            }
        };
    }]);

 ただし、このようにコントローラ内で画面遷移をする場合には問題ないのですが、HTMLテンプレートにパスを記述する場合にAタグ等を使って記述したくなります。そのような場合には、アプリケーションがhashモードか、HTML5モードのどちらで動作しているかに注意する必要があります。そのためには、筆者はリスト8のようなディレクティブを作成して利用しています。ディレクティブの作成方法は以前の記事を参照してください。

リスト8 ディレクティブを使った直接URLによる指定以外の指定方法(routes.jsの抜粋)
routes.directive('routeHref',['$location',function($location){
    return {
        restrict : 'A',
        scope : {
            'routeHref' : '@'
        },
        link : function($scope,$element,$attrs){
            $element.on('click',function(){
                $scope.$apply(function(){
                    $location.path($scope.routeHref);
                });
            });
        }
    }
}]);

 このようなディレクティブを作成することでHTMLテンプレート内では、リスト9のようにroute-href属性を使ってパスの指定が簡単に行えます。

リスト9 作成したディクレティ部を利用したパスの指定方法(views/item.htmlの抜粋)
<!-- (1) フッタでの一覧画面に遷移する際の記述 -->
<a class="btn btn-default" route-href="/list"><span>一覧</span></a>
<!-- (2) タスク一覧からの詳細画面に遷移する際の記述 -->
<a class="list-group-item" ng-repeat="item in items" route-href="/item/{{item.uid}}">
  <!-- 省略 -->
</a>

画面遷移におけるイベント処理

 SPAとしてアプリケーションを作成するとルート変更(画面遷移)のたびに実際にサーバにアクセスしているわけではないので、そのままでは一般的にアクセスログなどを取得することができません。従って、アプリケーション内で画面遷移が行われた時に各自でそのための処理をしなければなりません。ngRouteサービスでは画面遷移をする際に表3に示すイベントが発火されるのでそのイベントを利用して実現することができます。

表3 画面遷移におけるイベント
イベント名 説明
$routeChangeStart ルート変更が行われる前のイベント。画面遷移を取り消すなどの処理が可能
$routeChangeSuccess ルート変更が行われた後のイベント
$routeUpdate ルートが変更された時(ただし、when/otherwiseでのreloadOnSearchでfalseが指定されたとき)
$routeChangeError ルート変更でエラーが発生した時

 リスト10はこのイベント処理を使った時のサンプルコードです。

リスト10 ルート変更時のイベント処理(routes.jsの抜粋)
routes.run(['$rootScope','$location',function($rootScope,$location){
    // (1) ルート変更(画面遷移)が行われた時のイベント処理
    $rootScope.$on('$routeChangeSuccess',function(event,cur,prev){
        if(window.ga){
            // 例えば、以下のようにしてAnalyticsでのPVとして処理する
            // window.ga('send', 'pageview', {page: $location.path()});
        }
    });
    //  (2) ルート変更(画面遷移)が行われる前のイベント処理
    $rootScope.$on('$routeChangeStart',function(event,next,cur){
        if(!cur && $location.path().indexOf('/item') == 0){
            event.preventDefault();  //(3)ルート変更を中止
            $location.path('/list');
        }
    });
}]);

 (1)では、画面遷移が行われた時にGoogle Analyticsのページビューのトラッキングをすることを想定したコードです。このサンプルでは、トラッキングコードを入れていませんので機能しませんが、トラッキングコードとGoogle Analytics APIを参考に任意のトラッキング処理が行えます。(2)では、直接詳細ページにアクセスした場合、つまり、/item/35のようなパスに直接アクセスした際には一覧ページにリダイレクトする処理を記述しています。実際にルート変更を行わないようにするには(3)のようにpreventDefault()メソッドを使ってルート変更をキャンセルすることができます。

最後に

 今回はSPAを構築する際にngRouteを利用しましたが、サードパーティのUI-Routerというものも存在し、こちらを利用されている方も多くいます。

 UI-Routerはテンプレートの入れ子やルートに名前を指定できるなどngRouteよりも高機能になっています。ただし、ngRouteよりも少々複雑になっているのでSPAを初めて作成する場合には、ngRouteを利用し、その後、ngRouterで具体的な不都合が生じたら利用を検討するとよいでしょう。おおよそ同じような考え方で作成されているために非常に移行もしやすくなっています。

 SPAでのWebアプリケーションが作れるようになると、これまでWebアプリケーションでは作れないと思っていたようなものも作れるようになりますので、これまでのWebアプリケーションとは一味違うアプリケーション作成にチャレンジしてください。

参考資料

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
AngularJSではじめるJavaScriptフレームワーク開発スタイル連載記事一覧

もっと読む

この記事の著者

山田 祥寛(ヤマダ ヨシヒロ)

静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト」代表。主な著書に「独習シリーズ(Java・C#・Python・PHP・Ruby・JSP&サーブレットなど)」「速習シリーズ(ASP.NET Core・Vue.js・React・TypeScript・ECMAScript、Laravelなど)」「改訂3版JavaScript本格入門」「これからはじめるReact実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

WINGSプロジェクト 小林 昌弘(コバヤシ マサヒロ)

WINGSプロジェクトについて>有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛...

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/8988 2015/10/14 14:00

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング