The Perfect Mix to Create a Hybrid App: Cordova/Ionic Framework, AngularJS & WordPress
Do we really need an app when we already have a responsive website?
Reasons for building an app
- Client says: It's cool to have an app (prestige?)
- The data is already there! WordPress!
- Whatever :-)
Now that we cleared this up ...
Reasons for a hybrid app
- The guy who did the WP site can do it :-)
- Easier to do than the "native" way (Really now? :-)
- Cool looking mobile app framework like Ionic
To Begin With:
A couple of slides of an Ionic App with default styling. (Custom are only the logo in the header and its color)
Except two static pages all content you see is coming from the WordPress site via API.
The Posts View
Default Ionic list view, loading the number of posts set in "Reading" in the WP Admin.
Header bar is kept simple. There's only the hamburger (menu) icon, on the right "Search", "Info (leading to the static WordPress pages for this site), plus a Contact form.
Single Post View
There is only the title, post thumbnail and content on it, plus a "Share this" button.
Naturally, typical post meta data like author, date, custom fields and so on, could be included.
Sharing Works
For Sharing there's only one Cordova plugin you ever want to use:
https://github.com/EddyVerbruggen/SocialSharing-PhoneGap-Plugin
Ionic Sidemenu
A basic menu. We've got a separate search page, which gets search results directly from WordPress (in near real-time, a second or so delay).
"Contact Us" features a true contact form being processed on the server.
"Find Us" includes a Google Map.
Google Map
Besides the "Contact Us" page featuring the contact form this is the only page NOT powered by WordPress data.
Ionic
Is Ionic Framework the coolest front-end SDK for creating hybrid apps with HTML 5? You'll be the judge!
http://ionicframework.com/
AngularJS
Ionic comes with AngularJS, the popular web application Javascript framework maintained by Google.
https://angularjs.org/
AngularJS services (factories) will get all the data, and controllers put it into shape.
Isn't that Phonegap?
Phonegap by Nitobi was bought by Adobe in 2011.They have an app "Build" Service.
Cordova by Apache is what's underneath Phonegap:
http://cordova.apache.org/
How do you start?
WordPress JSON API
https://wordpress.org/plugins/json-api/other_notes/
WordPress will bring a REST (JSON) API into core at some point.
Head over to Ionic and Get Started:
http://ionicframework.com/getting-started/
- You need Node, the Ionic CLI, plus all the necessary dependencies for your platform.
- Install Ionic with (on Windows without $):
$ npm install -g cordova ionic
- Start a Project with a sidebar menu:
$ ionic start myApp sidemenu
Run it
$ cd myApp $ ionic platform add ios $ ionic build ios $ ionic emulate ios
Replace ios with android if you build for that platform.
For normal testing in the browser simply run this from your project directory:
$ ionic serve
Fetching data with AngularJS $http
AngularJS has an excellent service for communicating with HTTP servers:
https://docs.angularjs.org/api/ng/service/$http
angular.module('myApp.services', [])
.factory('MyPostsData', function($http, $q, MyPostsStorage) {
....
}
We Need Factories
Factory 1:
MyPostsData
Purpose:
Setting the var "data" for holding the incoming data, the JSON URL, the post ID, all stuff that our controller later needs.
Factory 2:
MyPostsStorage
Purpose:
Retrieves and stores the posts in JSON, using "angular.fromJSON" and "angular.toJSON"
Generic factory to store incoming posts in HTML 5 Local Storage
Subtitle
.factory('MyPostsStorage', function() {
return {
retrieve: function() {
var myPosts = window.localStorage['myposts'];
if(myPosts) {
return angular.fromJson(myPosts);
}
return {};
},
save: function(myPosts) {
window.localStorage['myposts'] = angular.toJson(myPosts);
},
...
WordPress Posts Pagination (Make "Load More" work)
JSON returns the number of pages your posts make up in total. This depends on the setting in WP Admin "Reading": "Blog Pages show at most." E.g. if you have 17 posts in total and blog posts to be shown is set at 5, it will read: ""pages":4.
angular.module('myApp.controllers', [])
//Main Posts (Homepage)
.controller('MyPostsCtrl', function($scope, $http, $ionicLoading, MyPostsData,
MypPostsStorage, $timeout) {
...
$scope.loadPosts = function () {
$http({method: 'JSONP', url: MyPostsData.getURL() + 'page=' + $scope.page
+ '&callback=JSON_CALLBACK', timeout: 5000}).
success(function(data) {
...
$scope, $scope, $scope
success(function(data) {
$scope.more = data.pages !== $scope.page;
$scope.posts = $scope.posts.concat(data.posts);
MyPostsData.setData($scope.posts);
MyPostsStorage.save($scope.posts);
$ionicLoading.hide();
}).
error(function() {
$scope.posts = MyPostsStorage.retrieve().posts;
MyPostsData.setData(MyPostsStorage.retrieve().posts);
$ionicLoading.hide();
});
$scope is the glue between factories and controllers
If the user clicks the "Load More" button the next 5 posts are loaded which are appended to the existing posts storage.
Ok, so posts are in. What next?
First off:
The cool thing is there's no need to bother the WordPress API for more posts data.
No, it isn't
Using the JSON API I would need to do the following requests:
-
Method: get_category_index
Returns an array of active categories.
-
Method: get_category_posts
Returns an array of posts/pages in a specific category.
- Method: get_post
Returns a single post object.
Retrieving the post categories
Accessing HTML Local Storage only, using nested angular.forEach to retrieve all categories."Push" adds each found category to the array.
.controller('CatsCtrl', function($scope, MyPostsStorage) {
data = MyPostsStorage.retrieve();
$scope.categories = [];
angular.forEach(data, function(post, index){
angular.forEach(post.categories, function(category, index){
$scope.categories.push(category);
});
});
})
How about duplicate entries?
angular-filter.js filters (unique) them based on unique category slugs.
This happens in the view (where you set up the categories list to be shown with links to posts):
<ion-list>
<ion-item ng-repeat="cat in categories | unique: 'slug' | orderBy:'title'" ...>
One last bit of functionality before we turn to "Views"
How to search your WP site from the app?
Method: get_search_results
Returns an array of posts/pages in response to a search query.
Using ionic.debounce() the search is called only every 500ms.
//Search Form
.controller('SearchCtrl', function($ionicLoading, $scope, $http) {
var doSearch = ionic.debounce(function(query) {
var url = 'http://talktechwith.me/api/get_search_results/?search=';
$http({method: 'JSONP', url: url + $scope.query
+ '&post_type=post&callback=JSON_CALLBACK', timeout: 5000}).
success(function(data) {
...
Views
It's all done through AngularJS expressions (you know inside those double braces) in these HTML templates
All Posts View
{{$index}} is set to the post id. See "ng-repeat":
https://docs.angularjs.org/api/ng/directive/ngRepeat
<card>
<ion-list>
<ion-item class="item-thumbnail-left" ng-repeat="post in posts
| filter: query" href="#/app/allposts/{{$index}}">
<img ng-src="data:image/jpeg;base64,{{post.custom_fields.base64thumb[0]}}" alt="
{{post.title}}" />
<span class="item-text-wrap" ng-bind-html="post.title"></span>
<i class="icon ion-chevron-right icon-accessory"></i>
<span class="item-text-wrap" ng-bind-html="post.excerpt"></span>
</ion-item>
Thumbnail is in base64 (custom field), then you have "post.title", "post.exercpt".
Single Post View
Date format returning from JSON for this post would be: "2014-04-17 10:37:50".
A custom AngularJS filter takes care of that.
Post thumbnail is cached.
<div class="card">
<div class="item item-text-wrap">
<h1 ng-bind-html="post.title"></h1>
</div>
<div class="item item-text-wrap">
<p ng-bind-html="post.date | customDateFormat"></p>
</div>
<div class="item item-text-wrap single-img">
<img ng-cache ng-src="{{post.thumbnail_images.singlethumb.url}}" alt="" />
</div>
<div class="item item-text-wrap" ng-bind-html="post.content">
</div>
Issues, Snags on the WordPress side?
Zero.
All that's left to do is include more content (from custom fields). Look into authentication when doing JSON calls.
What would be cool!
Include actual functionality from plugins (e.g. a calendar on the site, and so on) from within the app. Any ideas?
Issues, Quirks ...
Some were Ionic, some with Cordova plugins. Normally someone already had the issue you had so you find help in the relevant forums. This relates e.g. to implementing Google Maps, Google Analytics etc.
Things I still have to do
Cordova: What to do when the app user is offline, online? Test push (if needed).
Ionic: Styling, solve some display quirks. Add "pull to refresh perhaps using Ion-Refresher.
AngularJS: Probably do some refactoring.
Contact
Thank you!
The Perfect Mix to Create a Hybrid App: Cordova/Ionic Framework, AngularJS & WordPress
By afeuz
The Perfect Mix to Create a Hybrid App: Cordova/Ionic Framework, AngularJS & WordPress
Yes, WordPerss can easily power the data needs of a hybrid app made with Ionic Framework & AngularJS, not to forget Cordova.
- 6,889