【連載】ハイブリッドアプリ開発で貯金管理アプリを作る【Cordova・Monaca・OnsenUI・AngularJS】
1章 UI開発
1-2【UI開発】OnsenUIを使ったページ遷移の実装2【Navigator編】
このページは、過去の記事
を最新化したもの。
www.sky-limit-future.com
こちらの続きとなっている。
ナビゲーション型画面遷移
以下、ドキュメントから引用
コンポーネントは、ページスタックの管理機能と、画面遷移時のアニメーション効果を提供します。ページスタックに新しいページが追加されると、自動的にアニメーションが行われ、ページが表示されます。スタック内のすべてのページは 要素で表されます。そのため、 コンポーネントの直下には コンポーネントのみ配置できます。
通常は、ページ上部にツールバーを設置します。そのため、の下には コンポーネントを配置するのが一般的です。ツールバーには、戻るボタンを設置したり、ページタイトルを描画したりします。
ja.onsen.io.s3-website-us-east-1.amazonaws.com
index.htmlは前回の記事と同様のものを使う。
主にNavigatorのpushPage()とpopPage()を使用する。
例えば、一覧画面でリストを押下した場合、押下したアイテムの詳細画面に遷移する場合はpushPage()を使う。
注意点は、Navigatorで遷移した場合は、tabbarやtoolbarが表示されなくなること。 これはtabbarのカバー範囲外に行くから。
もしtabbarを表示したまま画面遷移したい場合は、前回の記事で説明したように、ng-clickに遷移するためのメソッドを定義する。
ons-navigator
共通ページをons-navigatorタグで囲っている。
var属性で指定した「myNavigator」をangular側で拾って、イベント定義などを実装する。
<!-- 共通ページ --> <ons-navigator var="myNavigator"> <ons-page ng-controller="pageCtrl as pctrl"> <ons-toolbar id="toolbar"> <div class="center">{{pctrl.title}}</div> <!-- 一覧ページから詳細ページへの遷移ボタンを実装 --> <div class="right" ng-if="pctrl.title == '一覧'"> <ons-button ng-click="myNavigator.pushPage('listDetail.html');">詳細画面へ</ons-button> </div> </ons-toolbar> <ons-tabbar position="bottom"> <ons-tab page="home.html" label="ホーム" icon="home" active></ons-tab> <ons-tab page="list.html" label="一覧" icon="list"></ons-tab> <ons-tab page="history.html" label="履歴" icon="history"></ons-tab> <ons-tab page="simulation.html" label="計算" icon="calculator"></ons-tab> <ons-tab page="config.html" label="設定" icon="gear"></ons-tab> </ons-tabbar> </ons-page> </ons-navigator>
pushPage()とpopPage()
pushPage()は新しいページを表示する。popPage()は遷移前のページを表示する。(戻る)
よく使うoptionとしてはanimationとdata。
animationは画面表示時の動きを決める。
dataは遷移先へのデータの受け渡しを行う。
ドキュメントを読めばわかると思うが。
https://ja.onsen.io/v2/api/angular1/ons-navigator.html#method-pushPage
<ons-button ng-click="myNavigator.pushPage('listDetail.html');">詳細画面へ</ons-button>
これはoptionなし。
animationには
slide
fade
lift
などがある。
ここでは試さないが、例えばslideを指定する場合はこんな感じ
<ons-button ng-click="myNavigator.pushPage('listDetail.html', {animation:slide});">詳細画面へ</ons-button>
データを次の画面に渡したいときはdataオプションを使う。
◆html
<!-- 共通ページ --> <ons-navigator var="myNavigator"> <ons-page ng-controller="pageCtrl as pctrl"> <ons-toolbar id="toolbar"> <div class="center">{{pctrl.title}}</div> <!-- 一覧ページから詳細ページへの遷移ボタンを実装 --> <div class="right" ng-if="pctrl.title == '一覧'"> <ons-button ng-click="myNavigator.pushPage('listDetail.html',{data: {name: 'duotaro',age: '22'}})">詳細画面へ</ons-button> </div> </ons-toolbar> <ons-tabbar position="bottom"> <ons-tab page="home.html" label="ホーム" icon="home" active></ons-tab> <ons-tab page="list.html" label="一覧" icon="list"></ons-tab> <ons-tab page="history.html" label="履歴" icon="history"></ons-tab> <ons-tab page="simulation.html" label="計算" icon="calculator"></ons-tab> <ons-tab page="config.html" label="設定" icon="gear"></ons-tab> </ons-tabbar> </ons-page> </ons-navigator> <!-- 詳細画面画面 --> <ons-template id="listDetail.html"> <ons-page id="detailPage" ons-show="pctrl.title = '詳細'"> <div class="content" ng-app="myApp"> <div class="main" ng-controller="listDetailCtrl as ldctrl"> <p>詳細画面</p> <p>{{ldctrl.name}}</p> <p>{{ldctrl.age}}</p> </div> </div> </ons-page> </ons-template> <script src="js/controller/listController.js"></script>
以下、サンプルコード
listController.js
myApp.controller('listDetailCtrl', function(){ this.name = '初期名称'; this.age = '0'; // myNavigator.pushPageで送ったdataを受け取る var data = myNavigator.topPage.data; // 正しく受け取ることができたら、値を取得 if(data != undefined){ this.name = data.name; this.age = data.age; } });
index.htmlでlistController.jsを読み込むのを忘れないように。(よくやる)
詳細画面には、ng-controller属性を追加した。
<div class="main" ng-controller="listDetailCtrl ac ldctrl"> <p>詳細画面</p> <p>{{ldctrl.name}}</p> <p>{{ldctrl.age}}</p> </div>
こうすれば、listDetailCtrlで定義した値がindex.htmlで使えるようになる。
実際に遷移してみると、問題があるのが分かると思う。
元の画面にもどれない。
この画面はタブが表示されないので、遷移前の戻る用ボタンを設置する必要がある。
toolbarにある方が、画面全体の有効活用が可能なので、この画面にはtoolbarを独自で持つようにした。
<!-- 詳細画面画面 --> <ons-template id="listDetail.html"> <ons-page id="detailPage" ons-show="pctrl.title = '詳細'"> <!-- START toolbar追加 --> <ons-toolbar id="toolbar"> <!-- 一覧ページへの戻るボタンを実装 --> <ons-back-button>戻る</ons-back-button> <div class="center">{{pctrl.title}}</div> </ons-toolbar> <!-- END toolbar追加 --> <div class="content" ng-app="myApp"> <div class="main" ng-controller="listDetailCtrl as ldctrl"> <p>詳細画面</p> <p>{{lectrl.name}}</p> <p>{{lectrl.age}}</p> </div> </div> </ons-page> </ons-template>
これで問題はなくなった。
ちゃんとデータの受け渡しもできている。
上記の実装では
<!-- 詳細画面画面 --> <ons-template id="listDetail.html"> <ons-page id="detailPage" ons-show="pctrl.title = '詳細'"> <ons-toolbar id="toolbar"> <!-- 一覧ページへの戻るボタンを実装 --> <ons-button ng-click="myNavigator.popPage()">戻る</ons-button> <div class="center">{{pctrl.title}}</div> </ons-toolbar> <div class="content" ng-app="myApp"> <div class="main" ng-controller="listDetailCtrl as ldctrl"> <p>詳細画面</p> <p>名前:{{ldctrl.name}}</p> <p>年齢:{{ldctrl.age}}</p> </div> </div> </ons-page> </ons-template>
ここで、前回と本記事までの実装内容をまとめる。
(controllerはデータ受け渡し用のサンプルで作成しただけなので、ここではなかったものとする)
index.html
<!DOCTYPE HTML> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"> <meta http-equiv="Content-Security-Policy" content="default-src * data: gap: https://ssl.gstatic.com; style-src * 'unsafe-inline'; script-src * 'unsafe-inline' 'unsafe-eval'"> <script src="components/loader.js"></script> <script src="lib/angular/angular.min.js"></script> <script src="lib/onsenui/js/onsenui.min.js"></script> <script src="lib/onsenui/js/angular-onsenui.min.js"></script> <link rel="stylesheet" href="components/loader.css"> <link rel="stylesheet" href="lib/onsenui/css/onsenui.css"> <link rel="stylesheet" href="lib/onsenui/css/onsen-css-components.css"> <link rel="stylesheet" href="css/style.css"> </head> <body> <!-- 共通ページ --> <ons-navigator var="myNavigator"> <ons-page ng-controller="pageCtrl as pctrl"> <ons-toolbar id="toolbar"> <div class="center">{{pctrl.title}}</div> <!-- 一覧ページから詳細ページへの遷移ボタンを実装 --> <div class="right" ng-if="pctrl.title == '一覧'"> <ons-button ng-click="myNavigator.pushPage('listDetail.html')">詳細画面へ</ons-button> </div> </ons-toolbar> <ons-tabbar position="bottom"> <ons-tab page="home.html" label="ホーム" icon="home" active></ons-tab> <ons-tab page="list.html" label="一覧" icon="list"></ons-tab> <ons-tab page="history.html" label="履歴" icon="history"></ons-tab> <ons-tab page="simulation.html" label="計算" icon="calculator"></ons-tab> <ons-tab page="config.html" label="設定" icon="gear"></ons-tab> </ons-tabbar> </ons-page> </ons-navigator> <!-- ホーム画面 --> <ons-template id="home.html"> <ons-page id="homePage" ons-show="pctrl.title = 'ホーム'"> <div class="content" ng-app="myApp"> <div class="main"> <ons-button ng-click="pctrl.changeConfigTab()">設定画面へ</ons-button> </div> </div> </ons-page> </ons-template> <!-- 一覧画面 --> <ons-template id="list.html"> <ons-page id="listPage" ons-show="pctrl.title = '一覧'"> <div class="content" ng-app="myApp"> <div class="main"> <ons-button ng-click="myNavigator.pushPage('listDetail.html');">詳細画面へ</ons-button> </div> </div> </ons-page> </ons-template> <!-- 詳細画面画面 --> <ons-template id="listDetail.html"> <ons-page id="detailPage" ons-show="pctrl.title = '詳細'"> <!-- START toolbar追加 --> <ons-toolbar id="toolbar"> <!-- 一覧ページへの戻るボタンを実装 --> <ons-back-button>戻る</ons-back-button> <div class="center">{{pctrl.title}}</div> </ons-toolbar> <!-- END toolbar追加 --> <div class="content" ng-app="myApp"> <div class="main"> </div> </div> </ons-page> </ons-template> <!-- 編集画面 --> <ons-template id="listEdit.html"> <ons-page id="editPage" ons-show="pctrl.title = '編集'"> <div class="content" ng-app="myApp"> <div class="main"> <p>編集画面</p> </div> </div> </ons-page> </ons-template> <!-- 履歴画面 --> <ons-template id="history.html"> <ons-page id="historyPage" ons-show="pctrl.title = '履歴'"> <div class="content" ng-app="myApp"> <div class="main"> <ons-button ng-click="myNavigator.pushPage('chart.html');">グラフ画面へ</ons-button> </div> </div> </ons-page> </ons-template> <!-- グラフ画面 --> <ons-template id="chart.html"> <ons-page id="chartPage" ons-show="pctrl.title = 'グラフ'"> <div class="content" ng-app="myApp"> <div class="main"> <p>グラフ画面</p> </div> </div> </ons-page> </ons-template> <!-- 計算画面 --> <ons-template id="simulation.html"> <ons-page id="simPage" ons-show="pctrl.title = '計算'"> <div class="content" ng-app="myApp"> <div class="main"> <p>計算画面</p> </div> </div> </ons-page> </ons-template> <!-- 設定画面 --> <ons-template id="config.html"> <ons-page id="configPage" ons-show="pctrl.title = '設定'"> <div class="content" ng-app="myApp"> <div class="main"> <p>設定画面</p> </div> </div> </ons-page> </ons-template> <script> // モジュールの定義 var myApp = ons.bootstrap('myApp',[]); /** * 画面遷移用コントローラ */ myApp.controller('pageCtrl', function() { // タブバーを取得 var tabbar = document.querySelector("ons-tabbar"); // 1つ目のタブへ遷移 this.changeHomeTab = function(){ tabbar.setActiveTab(0); }; // 2つ目のタブへ遷移 this.changeListTab = function(){ tabbar.setActiveTab(1); } // 3つ目のタブへ遷移 this.changeHistoryTab = function(){ tabbar.setActiveTab(2); } // 4つ目のタブへ遷移 this.changeSimTab = function(){ tabbar.setActiveTab(3); } // 5つ目のタブへ遷移 this.changeConfigTab = function(){ tabbar.setActiveTab(4); } }); </script> </body> </html> <script src="js/controller/listDetailController.js"></script>
ここまでで、アプリの骨格ができた感じ。
Angularの実装方針
余談。僕がAngularで$scoreを使わなかったり、ng-controllerの中で「as」を使っている実装方針は
ここを参考にさせていただいた。この記事を見てAngularを始めようと思ったのを覚えている。
こちらの記事もすでに2年前のものになっているので。現在はどういったものがベストなのか考える必要があるかも。
今後はAngular2やvue.jsを使ったハイブリッドアプリ開発とPWA開発をやっていきたい。
以上。