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