アシアルブログ

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

ANGULAR UにてMonaca/Onsen UIの発表を行いました

6月に開催されたANGULAR UにてAndreasがMonacaおよびOnsen UIについてプレゼンを行いました。この記事ではその意訳版になります。実際の発表の様子は下記の動画をご覧ください。





私はスウェーデンで生まれ育ったのですが、今は日本で働いています。仕事は二つあり、一つはハイブリッドアプリ開発プラットフォームであるMonaca、もう一つはハイブリッドアプリのUIコンポーネントライブラリであるOnsen UIの開発となっています。





自己紹介



まずハイブリッドアプリに関して説明します。ハイブリッドアプリはWebアプリをスマートフォンのネイティブコンポーネントであるWebViewを使ってアプリにする技術です。そのため、HTMLやJavaScriptスタイルシートを使ってスマートフォンアプリが開発できます。





ハイブリッドアプリについて



なぜハイブリッドアプリを選択するかと言うと、





といった特徴があるからです。



次にハイブリッドとネイティブアプリの違いについてです。FacebookのCEOであるザッカーバーグ氏は実行速度を理由にHTML5からネイティブに開発の軸を変更しました。しかしそれから数年経ち、Ruby on Railsの開発者で知られるDHH氏は昨年、パフォーマンスは大幅に改善していると書いています。



ではここからMonacaを使ったCordovaアプリ開発について説明します。まずワークフローです。





Monacaのワークフロー



コーディングはローカルのエディタ、またはCloud IDEを使ってブラウザ上での開発が選択できます。テストはMonacaデバッガーを使って行います。コードを編集すると自動的に同期する仕組みになっています。



ビルドはMonacaクラウド上で行います。ブラウザを使って開発できますので、iOSアプリを開発するのにMac OSXが必要と言ったことはありません。



デモをお見せします。



左側がクラウドIDEです。コードの自動補完が入っています。Angularの補完も可能です。



編集したら、Runをクリックすると、スマートフォンMonacaデバッガー上でアプリが実行されます。



ファイルを編集するとすぐにMonacaデバッガーが再読込されて変更が反映されます。さらにデバッガーはインスペクターも使えるようになっています。





Monaca IDEのデモ



さて今回はAngularのカンファレンスですが、まだAngular向きの話をしていません。そこで知って欲しいのがOnsen UIです。Onsen UIはAngularベースのUIフレームワークです。



Onsen UIの特徴は、





になります。



名前の由来ですが、Onsenというのは日本語で温泉(hot spring)のことです。他の言い方ではスパ(SPA)とも言います。SPAといえばSingle Page Applicationです。そこからとっています。



Onsen UIはアジア圏、特に日本において成長しています。とはいえグローバルで見ればまだまだでIonicのがよく知られているでしょう。Onsen UIの事例としてはヘルス系、メッセージ系など数多くあります。





Onsen UIを使ったアプリ



Onsen UIは数多くのUIコンポーネントを提供しています。例えばスイッチであったり、レンジであったり、タブバーなど様々です。





Onsen UIのUIコンポーネント



これらを組み合わせることで様々なネイティブアプリ風のUIが実現できます。これらはAngularを使って作られています。





Onsen UI×Angular



次に次期バージョンであるOnsen UI 2.0について説明します。特徴としては、





になります。



構成としては、Onsen CoreとOnsen CSSの二つに分かれる形になります。Onsen CoreはWeb Componentを使っており、Angular 1.x系または2.0系であったり、Reactにバインディングして使うことができます。





Onsen 2.0 の構造



なぜWeb Componentsを使うかと言うと、



  • Angular 1.x系のディレクティブよりも軽量かつシンプルなAPIである
  • Angular 2.0と組み合わせて使うことができる
  • Onsen UI 1.x系のナレッジを活かして再開発できる
  • 複数のフレームワークをサポートするのが容易になる


といったことが挙げられます。



まずOnsen 2.0とAngular 1.xとの組み合わせはこのようなコードになります。



次にOnsen 2.0とAngualr 2.0の場合です。多少書き方は変わりますが、殆ど変わっていないのが分かるかと思います。



現在のOnsen 2.0の開発状況ですが、まだまだ開発中ですが、UIコンポーネントをWeb Componentsに書き換え中です。



Angular 2.0と組み合わせたデモアプリを紹介します。これはGitHubでコードを公開していますのでぜひ見てください。





Onsen 2.0×Angular 2.0のデモ



Angular 2.0はこれまでと大幅に変わっており、多くの点において変更が必要になります。ぜひ皆さんの協力が欲しいと思っています。Onsen UIは最新ビルドがいつでもダウンロードできるようになっています。ぜひ試して問題があれば報告したり、pull reqを送ってください。

Easily create Master/Detail pages in Onsen UI

Most mobile apps need a way to transition from one page to another and have the data shared between those pages. Onsen UI makes it easy to do so using AngularJS Service and Controller.



Without further ado, will we create an app that looks like this:





1. Create a project using Onsen UI Minimum Template


1. Log in to monaca.mobi


2. Create a new project


3. Choose Onsen UI Minimum Template


You can have a look at this tutorial for detail instruction on how to do this.


Now your project should look like this:


2. Create a service to hold our data


Create a file named data.js with the following content:






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;
});




We named our service Data which will be referenced later.


3. Display the data in page1.html


1. page1.js


Create a file named page1.js with the following content:





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 We reference the Data service by asking angular to inject it into Page1Controller
2 We assign Data.items to $scope.items so that we can bind it to our html
3 showDetail() function will be called when user click an item. We get the selected item using index, and assigned the selected item to Data server so that we can later reference it from Page2Controller


2. page1.html


Replace page1.html with the following content:





<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 We tell angular to use Page1Controller we defined in page1.js using ng-controller
2 We list all item in $scope.items using ng-repeat
3 When the user click an item, we want angular to call showDetail() function. Since we are using ng-repeat, we can use $index to get the index of the item



Insert these two lines into index.html





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


Make sure it looks like this:





<!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>


Now let's see if the items are displayed. Run the app and make sure you see something like this:





4. Show item's detail in page2.html


When an item on the list is clicked, we want to show its detail on page2.html


Remember we have defined showDetail function in page1.js that assigned the selected item to Data service (Data.selectedItem). So let's use it to display the detail.


1. Create page2.js with the following content:





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


Here we assign Data.selectedItem to $scope.item so that we can use in in page2.html



Insert this line into index.html





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


Make sure your file look something like this:





<!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>



3. page2.html


Replace page2.html with the following content:





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


Here we link page2.html to page2.js with ng-controller.


Now let's test our awesome app.


Click on Item 1 and make sure it transition to page2.html and you see something like this:





5. Conclusion


Onsen UI makes it easy to transition from pages to page as well as link data between them with just a few lines of code.


5. Complete Source Code


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}}