Building Native-Like PhoneGap Apps
Christophe Coenraets
http://coenraets.org
@ccoenraets
Holly Schinsky
http://devgirl.org
@devgirlfl
You
Agenda
- Pitfalls and Common Solutions
- Architecture
- Framework Landscape
- AngularJS
- Ionic
What's This?
A PhoneGap App!
Pluggable Data Adapters
Ajax/JSON
Memory
LocalStorage
WebSQL
cordova plugin add org.apache.cordova.dialogs
navigator.notification.alert(message,
callback,
title,
buttonName);
iOS 8 status: https://github.com/ftlabs/fastclick/issues/262
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>
Multi-Page vs Single-Page Architecture
|
Multi-Page |
Single-Page |
UI Generation Tier |
Server-Side |
Client-Side |
Language |
Java, .NET, PHP, RoR |
JavaScript |
Offline Support |
Limited |
Yes |
Page Transitions |
Browser |
Developer |
Performance |
Laggy |
Fast |
New Challenges
- Create large, complex apps in JavaScript
- Avoid problems in a long lived DOM
- Create complex UI in JavaScript
Building HTML with JavaScript
var html =
'' +
'
' +
'
' +
'
Geometrixx
' +
'' +
'
' +
'' +
'
' +
'
' + product.name + '
' +
'
' + product.category + '
' +
'
' +
'
' + product.price + '
' +
'
' +
'' +
' ' +
'
' +
'' +
'' +
'
';
Using Templates
{{this.name}}
{{this.category}}
{{this.price}}
Templates
- Handlebars.js
- Mustache.js
- Underscore.js (built-in)
- AngularJS (built-in)
Provide Structure to Your Application
MV*
Model
var Product = function() {
this.url = "/product";
this.validate = function() {
};
});
View
var ProductView = function () {
this.initialize = function () {
};
this.render = function() {
};
}
Controller
var JSONPAdapter = function(url) {
this.findById = function(id) {
return $.ajax({url: url + "/" + id, dataType: "jsonp"});
}
this.findByName = function(searchKey) {
return $.ajax({url: url + "?name=" + searchKey, dataType: "jsonp"});
}
}
Use Native Scrolling
#scroller {
overflow: auto;
-webkit-overflow-scrolling: touch;
position: absolute;
top: 48px;
bottom: 0px;
left: 0px;
right: 0px;
}
Use CSS Transitions
+
Hardware Acceleration
Slow
.page {
position: absolute;top: 0;left: 0;width: 100%;height: 100%;
}
.left {
left: -100%;
}
.center {
left: 0;
}
.right {
left: 100%;
}
.transition {
transition-duration: .25s;
}
Fast
.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;
}
https://github.com/ccoenraets/PageSlider
Frameworks
AngularJS
- MVC architecture for client app
- Dependency Injection
- Directives
- Data binding
- Templates
app.js
angular.module('myApp', ['controllers', 'services'])
index.html
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
})
});
- UI Layer on top of AngularJS
- UI Components
- UI Components are AngularJS Directives
- UI Patterns
- CLI built on top of Cordova
Performance
- Hardware accelerated animations
- Minimal DOM Manipulation
- Zero jQuery (you could still include it if you want)
Native Focused
- Modeled off of native SDKs
- Built to work with Cordova/Phonegap
Beautifully Designed
- Cohesive visual system
- Clean and simple
- Easy to customize
Complex Lists
- AngularJS Directive
- Buttons exposed by swiping
- Reorder
- Delete
{{ item.name }}
{{ item.quote }}
Tabs
- Nested views
- Each tab has its own nav history
Slide Box
Slide 1
Slide 2
Slide 3
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