A few days ago a reader posted a comment to a blog post I wrote that demonstrated a simple RSS reader built with the Ionic framework. Looking over the code I had written for that demo I realized there was a lot of room for improvement. I'm still no Angular expert, but I've learned a few things over the past few months and decided to update the code base. I thought it might be interesting to point out what I changed (especially if people better at Angular want to correct me) so folks could compare the differences.
I made three major changes to the code base. The first was to tweak how I handle Cordova's deviceready event within the Ionic code. Previously I had the default Ionic "run" code inside my controller. That was messy and not necessary, so I moved it back to the run
method in app.js:
.run(function($ionicPlatform, $rootScope, $location) {
$ionicPlatform.ready(function() {
// Hide the accessory bar by default (remove this to show the accessory bar above the keyboard
// for form inputs)
if(window.cordova && window.cordova.plugins.Keyboard) {
cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
}
if(window.StatusBar) {
StatusBar.styleDefault();
}
});
$rootScope.goHome = function() {
$location.path('/entries');
};
});
That cleaned up my controller a bit. Next, I added a service. When I first started working with Angular, I did almost everything in controllers because that was simpler, but it also made my code messy (imo). I moved all the logic of RSS parsing into its own service.
(function() {
/* global angular,window,cordova,console */
angular.module('rssappServices', [])
.factory('rssService', function($http,$q) {
var entries;
return {
getEntries: function(url) {
var deferred = $q.defer();
console.log('getEntries for '+url);
if(entries) {
console.log('from cache');
deferred.resolve(entries);
} else {
google.load("feeds", "1",{callback:function() {
console.log('googles init called');
var feed = new google.feeds.Feed(url);
feed.setNumEntries(10);
feed.load(function(result) {
entries = result.feed.entries;
deferred.resolve(entries);
});
}});
}
return deferred.promise;
}
};
});
}());
Note the use of deferreds here to handle the async nature of Google's RSS parsing. The end result of these two changes is a much simpler controller.
.controller('HomeCtrl', ['$ionicPlatform', '$scope', '$rootScope', '$cordovaNetwork', '$ionicLoading', '$location', 'rssService', 'settings', function($ionicPlatform, $scope, $rootScope, $cordovaNetwork, $ionicLoading, $location, rssService, settings) {
$ionicLoading.show({
template: 'Loading...'
});
$ionicPlatform.ready(function() {
console.log("Started up!!");
if($cordovaNetwork.isOnline()) {
rssService.getEntries(settings.rss).then(function(entries) {
$ionicLoading.hide();
$rootScope.entries = entries;
$location.path('/entries');
});
} else {
console.log("offline, push to error");
$ionicLoading.hide();
$location.path('/offline');
}
});
}])
The final change was how I set the title and RSS URL of the app. I had used rootScope variables before, but now I'm using Angular Constants, which is something I just discovered about a month or so ago:
.constant("settings", {
title:"Raymond Camden's Blog",
rss:"http://feeds.feedburner.com/raymondcamdensblog"
})
All in all, not a huge amount of changes, but it "feels" a heck of lot better architected now. As I said in the beginning, I welcome comments/criticisms about the techniques here - just post a comment. You can find the full source code here: https://github.com/cfjedimaster/Cordova-Examples/tree/master/rssreader_ionic