Building Native-Like Mobile Apps
with Cordova, AngularJS and Ionic

Christophe Coenraets
@ccoenraets

Me

Christophe Coenraets

Boston, MA

@ccoenraets

http://coenraets.org

https://github.com/ccoenraets

You

What's This?

A Hybrid App!


Cordova 3.x CLI

Creating and Building Projects

cordova create MyApp cd MyApp cordova platform add ios cordova platform add android cordova build ios cordova build android

Plugins

cordova plugin add org.apache.cordova.geolocation
cordova plugin add org.apache.cordova.file
cordova plugin add org.apache.cordova.dialogs
cordova plugin add org.apache.cordova.device
cordova plugin add org.apache.cordova.console
cordova plugin add org.apache.cordova.camera

PhoneGap CLI

Building in the Cloud

phonegap remote build ios phonegap remote build android

Your web app doesn't look like this anymore

Single Page Application

<html>
<head>
    <title>My App</title>
    <script src="app.js"></script>
</head>
<body></body>
</html>

New Challenges

cordova plugin add org.apache.cordova.dialogs

navigator.notification.alert(message,
                             callback,
                             title,
                             buttonName);

Slow

Click Me

click: 0ms

Fast

Click Me

touchend: 0ms

Left Center Right


class="left"
Left Center Right


class="center"
Left Center Right


class="right"

Hardware Acceleration

.page { position: absolute;top: 0;left: 0;width: 100%;height: 100%; transform: translate3d(0, 0, 0); } .left { transform: translate3d(-100%, 0, 0); } .center { transform: translate3d(0, 0, 0); } .right { transform: translate3d(100%, 0, 0); } .transition { transition-duration: .25s; }
You could solve these challenges individually, or...

"Native SDK"-Like Framework

Framework Landscape

AngularJS

  1. MVC architecture for client app
  2. Dependency Injection
  3. Directives
  4. Data binding
  5. Templates

app.js

angular.module('myApp', ['controllers', 'services'])

index.html

<body ng-app="myApp"></body>

services.js

angular.module('services', ['ngResource']) .factory('Product', function ($resource) { return $resource('http://localhost/product/:id'); }) .factory('Offer', function ($resource) { return $resource('http://localhost/offer/:id'); }) });

controllers.js

angular.module('controllers', ['services']) .controller('ProductList', function ($scope, Product) { $scope.products = Product.query(); $scope.deleteItem = function(product) { product.$delete({id: product.id}, function() { $scope.products = Product.query(); }); }; });

product-list.html

<div ng-repeat="product in products">

    <a href="#/product-detail/{{product.id}}">
        {{product.name}}
        <img ng-if="product.pic" ng-src="{{product.pic}}">
    </a>

    <a ng-click="deleteItem(product)">Delete</a>

</div>

Routing

myApp.config(function($stateProvider) { $stateProvider .state('app', { url: "/app", templateUrl: "templates/app.html" }) .state('app.product-list', { url: "/products", templateUrl: "templates/product-list.html", controller: ProductList }) .state('app.product-details', { url: "/products/:productId", templateUrl: "templates/product.html", controller: ProductDetails }) });

Code Organization

angular.module('product', ['ngResource', 'config']) .config(function ($stateProvider) { $stateProvider.state('app.product', { url: "/product", ... }); }) .factory('Product', function ($resource, HOST) { return $resource(HOST + 'product/:id'); }) .controller('ProductList', function ($scope, Product) { $scope.products = Product.query(); }); });
  1. UI Layer on top of AngularJS
  2. UI Components
  3. UI Components are AngularJS Directives
  4. UI Patterns
  5. CLI built on top of Cordova

Performance

Native-Like

Design

Lists

  • AngularJS Directive
  • Buttons exposed by swiping
  • Reorder
  • Delete
<ion-list> <ion-item ng-repeat="item in items" option-buttons="buttons" class="item-thumbnail-left"> <img ng-src="{{ item.pic }}"> <h2>{{ item.name }}</h2> <p>{{ item.quote }}</p> </ion-item> </ion-list>

Tabs

  • Nested views
  • Each tab has its own nav history
<ion-tabs tabs-type="tabs-icon-only"> <ion-tab title="Home" icon="ion-star"> <ion-nav-view></ion-nav-view> </ion-tab> <ion-tab title="Reviews" icon="ion-down"> <ion-nav-view></ion-nav-view> </ion-tab> <ion-tab title="Chat" icon="ion-chat"> <ion-nav-view></ion-nav-view> </ion-tab> </ion-tabs>

Side Menu

<ion-side-menu side="left"> <header class="bar bar-header"> <div class="title">Projects</div> </header> <ion-content has-header="true"> <div class="list"> <a href="#/work" class="item"> Work </a> <a href="#/home" class="item"> Home </a> </div> </ion-content> </ion-side-menu>

Action Sheet

$ionicActionSheet.show({ titleText: 'Modify your album', buttons: [ { text: 'Share' }, { text: 'Move' }, ], destructiveText: 'Delete', cancelText: 'Cancel', buttonClicked: function(index) { console.log('BUTTON CLICKED', index); return true; } });

Pull to Refresh

<ion-content> <ion-refresher on-refresh="refreshData()"> </ion-refresher> <!-- content --> </ion-content>

Let's Build an App

npm install -g cordova ionic ionic start loyalty sidemenu cd loyalty ionic platform ios ionic build ios

Loyalty App Demo

Credit

Ionic UI components slides (slides 29 to 36) are based on Ionic's own Present Ionic deck.

Thank You

Christophe Coenraets

Boston, MA

@ccoenraets

http://coenraets.org

https://github.com/ccoenraets