アシアルブログ

アシアルの中の人が技術と想いのたけをつづるブログです

OnsenUIを使った一覧と詳細画面の作り方

この記事は、英語版アシアルブログの翻訳記事です。
(原文はこちら

==============================
ほとんどのモバイルアプリでは複数のページ間でデータの共有・受け渡しを必要とします。
OnsenUIはAngularJSの機能を利用しながらページ間でのデータ受け渡しを実現しています。

実際のアプリでは以下のように作ることができます。




手順1. 『OnsenUI最小限のテンプレート』からプロジェクトを作成する



1-1. monaca.mobiにログインします。


1-2. 新しいプロジェクトを作成します。


1-3. 『OnsenUI最小限のテンプレート』を選択してプロジェクトを作成します



※詳しい作成方法についてはこのチュートリアルで紹介されています


新しいプロジェクトを作成するとこのようになります:



手順2.  データを保持するためのServiceを作成する



ここでは以下のようにdata.jsというファイルを作成します:



var myApp = angular.module('myApp');
myApp.factory('Data', function(){
    var data = {};
 
    data.items = [
        { 
            title: 'Item 1',
            description: 'Item 1 Description'
        },
        { 
            title: 'Item 2',
            description: 'Item 2 Description'
        },
        { 
            title: 'Item 3',
            description: 'Item 3 Description'
        }
    ]; 
 
    return data;
});


ここでは後で参照するServiceに「Data」と名付けています。

手順3. page1.htmlでデータを表示する



3-1. page1.js



以下のようにpage1.jsというファイルを作成します:



function Page1Controller($scope, Data){ // 1
    $scope.items = Data.items;  // 2
 
    $scope.showDetail = function(index){ // 3
        var selectedItem = Data.items[index];
        Data.selectedItem = selectedItem;
        $scope.ons.navigator.pushPage('page2.html', selectedItem.title);
    }
}



  • 1 : Page1Controllerにserviceにセットした「Data」を引数として渡します

  • 2: page1.htmlでバインディングを利用するために「Data.items」を「$scope.items」に格納します

  • 3:「showDetail()」関数はユーザーが一覧を選択した際に詳細ページを表示するための関数です。 画面遷移の前に「Data」に遷移先で使用したいデータを格納します



3-2. page1.html



Replace page1.html with the following content:
以下のようにpage1.htmlを書き換えて下さい:


<div class="page center" ng-controller="Page1Controller"> <!-- 1 -->
    <ons-list>
        <ons-list-item ng-repeat="item in items" ng-click="showDetail($index)">  <!-- 2 -->
            {{item.title}}  <!-- 3 -->
        </ons-list-item>
    </ons-list>
</div>



  • 1 : 先ほど定義した「Page1Controller」をng-controllerとしてタグに記述します。

  • 2: リストを繰り返し表示させるために全てのアイテムが入った配列データ($scope.items)をng-repeatに記述します

  • 3:リストに表示されたアイテムを選択した時にshowDetail()関数が呼ばれます。$indexにはng-repeatで使われた配列の添字が入ります



3-3. index.htmlにdata.jsとpage1.jsを関連付ける



index.htmlに以下の2行を書き加えてください。



<script src="data.js"></script>
<script src="page1.js"></script>


するとindex.htmlは以下のようになります:



<!doctype html>
<html lang="en" ng-app="myApp">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
  <link rel="stylesheet" href="plugins/plugin-loader.css">     
  <script type="text/javascript" src="plugins/plugin-loader.js"></script>
 
  <script>
    angular.module('myApp', ['onsen.directives']);   
 </script>    
 
  <script src="data.js"></script>
  <script src="page1.js"></script>
 
</head>
<body>    
 
  <ons-screen page="home_navigator.html"></ons-screen>
 
</body>
</html>



実際にどのように項目が表示されるか見てみましょう。
アプリを実行して以下のようになにか表示されることを確認してください:



手順4.  page2.htmlに詳細画面を作る



page1.htmlの一覧でリストが選択された時、page2.htmlに選択された項目の詳細を表示させましょう。

serviceの「Data」には page1.jsで定義したshowDetail()関数で選択したアイテムを格納していたことを思い出しましょう。
ここでは「Data」に格納した項目を使って詳細画面を表示します。

4-1. page2.jsを以下のように作成します





function Page2Controller($scope, Data){
    $scope.item = Data.selectedItem;   
}


ここではpage2.htmlでバインディングを利用するために「Data.selectedItem(選択されたリスト項目のデータ)」を「$scope.item」に格納しています。

4-2. index.htmlにpage2.jsを関連付けする



以下をindex.htmlに追記してください。


<script src="page2.js"></script>


index.htmlは以下のようになります:



<!doctype html>
<html lang="en" ng-app="myApp">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
  <link rel="stylesheet" href="plugins/plugin-loader.css">     
  <script type="text/javascript" src="plugins/plugin-loader.js"></script>
 
  <script>
    angular.module('myApp', ['onsen.directives']);   
 </script>    
 
  <script src="data.js"></script>
  <script src="page1.js"></script>
  <script src="page2.js"></script>
 
</head>
<body>    
 
  <ons-screen page="home_navigator.html"></ons-screen>
 
</body>
</html>


4-3. page2.html



page2.htmlを以下のように書き換えて下さい:



<div class="page center" ng-controller="Page2Controller"> <!-- 1 -->
    <h2>{{item.title}}</h2> <!-- 2 -->
    <p>{{item.description}}</p><!-- 2 -->
</div>




  • 1 : 先ほど定義した「Page2Controller」をng-controllerとしてタグに記述します。

  • 2: 「item」に格納された項目のデータを表示させます



実際にアプリでテストしてみましょう。
page1.htmlでItem1を選択するとpage2.htmlに遷移し、以下のように表示されます:


まとめ


Onsen UIを使うと簡単に画面遷移できるだけでなはく、画面間でのデータ受け渡しも数行の実装で実現することができます。

ソースコード全文



index.html


<!doctype html>
<html lang="en" ng-app="myApp">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
  <link rel="stylesheet" href="plugins/plugin-loader.css">     
  <script type="text/javascript" src="plugins/plugin-loader.js"></script>
 
  <script>
    angular.module('myApp', ['onsen.directives']);   
 </script>    
 
  <script src="data.js"></script>
  <script src="page1.js"></script>
  <script src="page2.js"></script>
 
</head>
<body>    
 
  <ons-screen page="home_navigator.html"></ons-screen>
 
</body>
</html>


data.js



var myApp = angular.module('myApp');
myApp.factory('Data', function(){
    var data = {};
 
    data.items = [
        { 
            title: 'Item 1',
            description: 'Item 1 Description'
        },
        { 
            title: 'Item 2',
            description: 'Item 2 Description'
        },
        { 
            title: 'Item 3',
            description: 'Item 3 Description'
        }
    ]; 
 
    return data;
});


page1.js


function Page1Controller($scope, Data){
    $scope.items = Data.items;
 
    $scope.showDetail = function(index){
        var selectedItem = Data.items[index];
        Data.selectedItem = selectedItem;
        $scope.ons.navigator.pushPage('page2.html', selectedItem.title);
    }
}


page1.html


<div class="page center" ng-controller="Page1Controller">
    <ons-list>
        <ons-list-item ng-repeat="item in items" ng-click="showDetail($index)">
            {{item.title}} 
        </ons-list-item>
    </ons-list>
</div>


page2.js


function Page2Controller($scope, Data){
    $scope.item = Data.selectedItem;   
}


page2.html
>>HTML

{{item.title}}


{{item.description}}