1. Code
  2. Mobile Development
  3. Ionic Development

Create a Mobile Application for Displaying Your Website RSS Content With Ionic

Scroll to top
Final product imageFinal product imageFinal product image
What You'll Be Creating

In this tutorial we will take a look at creating a mobile application which displays the RSS content of a website. We will configure the RSS URL and the application will download it, parse it and display the posts from the RSS. 

To create the mobile application, we will use the Ionic Framework v1 together with AngularJS. To complete this tutorial, you need to have some experience with JavaScript and HTML. Also, it helps if you've worked with AngularJS before. 

If you have never worked with Ionic Framework before, I recommend at least taking a look at the Getting Started guide as it gives you a quick insight into how things work.

Let's begin!

Setting Up the Ionic Project

I will assume that you have installed Node on your system and you also have the npm (the Node package manager). Installing the Ionic framework is as easy as running the following:

1
npm install -g cordova ionic

This will install both Cordova and Ionic on your computer. 

Cordova is the core technology for Ionic, and basically it allows us to have an embedded browser in our mobile application. In that browser we will be able to run all our HTML and JavaScript code. This is called a hybrid mobile application, as the application does not run native code, but runs inside the browser. 

Next to Cordova, Ionic adds to that the possibility of using AngularJS for writing our code, and it also adds a very neat UI framework.

With Ionic in place, we can create our project using the Ionic CLI, a very useful command-line tool. Ionic provides three default project templates which can be used as a starting point:

  • blank: as the name says, it's an empty project with only the minimal necessary components in place.
  • tabs: an application using tabs for navigating through its screens.
  • sidemenu: an application using a standard mobile side menu for navigation.

For this tutorial, we will be using the tabs application template. To start our project, let's run:

1
ionic start myWebsiteOnMobile tabs

Ionic will download and install all components needed, and it will create the project folder named myWebsiteOnMobile. Go into the project directory by running:

1
cd myWebsiteOnMobile

Because our application is a hybrid mobile application, we have the advantage of being able to run the application inside a browser. To do this, Ionic provides a neat built-in web server which runs our application like this:

1
ionic serve

This will open a browser with our application loaded, and it will look like this:

The Ionic homescreenThe Ionic homescreenThe Ionic homescreen

To stop the server, use Control-C on your command-line screen. To get a better idea of how the application looks on a mobile, you can use:

1
ionic serve --lab

This will open the application in the browser, showing an iOS and an Android preview of the app side by side.

The iOS and Android PreviewThe iOS and Android PreviewThe iOS and Android Preview

The tabs Ionic application template has three tabs: Status, Chats, and Account. In the next steps we will adjust the application to fit our needs.

How to Adjust the Default Ionic Tabs Template Application

For our application we will have two tabs:

  • Latest posts: showing a list of latest posts retrieved from the RSS feed.
  • Settings: where the user will be able to configure several aspects of the application.

From the Latest posts tab, the user will be able to click on any of the latest posts and see more information about the post, with the possibility of opening up the post in an external browser.

Since our Latest posts tab is similar to the Chats tab provided by the template, we will reuse that together with the Account tab, which will become our Settings tab. We can do all modifications with the Ionic webserver running, and Ionic will reload the app for us. This is a very neat feature which will speed up development.

As mentioned before, Ionic uses AngularJS, and the whole application is actually an AngularJS module. The module is defined in www/js/app.js, and here is also where the paths or routes of the application are defined. Each screen of the application has a corresponding route.

Let's remove the Status tab since we will not need it. To do this, we first need to change the default screen (or route) of our application to point to the Chats screen, which will become our main screen. The default screen is configured via $urlRouterProvider.otherwise(), so let's change that to:

1
$urlRouterProvider.otherwise('/tab/chats');

If we now reload http://localhost:8100 in our browser, we will see that the Chats tab will be loaded by default.

To remove the Status tab, we need to edit the www/templates/tabs.html file that holds the template for the tab component. We will remove the element:

1
  <!-- Dashboard Tab -->
2
  <ion-tab title="Status" icon-off="ion-ios-pulse" icon-on="ion-ios-pulse-strong" href="#/tab/dash">
3
    <ion-nav-view name="tab-dash"></ion-nav-view>
4
  </ion-tab>

When saving, we will see that the application now has only two tabs: Chats and Account.

While in the www/templates/tabs.html file we notice that there are some HTML tags that are not standard HTML, like ion-tabs, ion-tab, and ion-nav-view. These are actually AngularJS directives defined by the Ionic Framework. The directives are tags that pack functionality behind them, and they are very convenient ways to write more structured and more concise code.

In our case, the ion-tabs directive is the tabs component, which for each tab requires an ion-tab directive.

Let's change our tabs from Chat and Account to our required names Latest posts and Settings. To do this, we will modify several things in the www/templates/tabs.html file:

  • title attribute of the ion-tab elements which determines the text on the tab button. We will change that to Latest posts and Settings respectively.
  • href attribute of the ion-tab elements which points to the route or screen URL. We will change those to #/tab/latest-posts and #/tab/settings.
  • name attribute of the ion-nav-view elements to tab-latest-posts and tab-settings. These are the identifiers for the view templates used for the Latest posts and Settings screens.

As a result, www/templates/tabs.html should look like this:

1
<ion-tabs class="tabs-icon-top tabs-color-active-positive">
2
3
  <!-- Latest posts Tab -->
4
  <ion-tab title="Latest posts" icon-off="ion-ios-chatboxes-outline" icon-on="ion-ios-chatboxes" href="#/tab/latest-posts">
5
    <ion-nav-view name="tab-latest-posts"></ion-nav-view>
6
  </ion-tab>
7
8
  <!-- Settings Tab -->
9
  <ion-tab title="Settings" icon-off="ion-ios-gear-outline" icon-on="ion-ios-gear" href="#/tab/settings">
10
    <ion-nav-view name="tab-settings"></ion-nav-view>
11
  </ion-tab>
12
13
14
</ion-tabs>

After making these changes, we will get some errors. This is because we also have to adjust our routes to use the new identifiers we have used. In www/js/app.js, we need to change the state identifiers, the view identifiers and the url for each route according to what we have set above.

For each route (or screen), there is a controller defined. This is a basic MVC (Model-View-Controller) design pattern. Controllers are defined within the file www/js/controllers.js. For consistency purposes, we will change the names of the controllers in both www/js/app.js and www/js/controller.js:

  • ChatsCtrl becomes LatestPostsCtrl.
  • ChatDetailCtrl becomes PostDetailCtrl.
  • AccountCtrl becomes SettingsCtrl.

Also, for each route we have a view template defined, so let's change them too. Edit www/js/app.js and modify templateUrl like this:

  • Change tab-chats.html to tab-latest-posts.html. Also rename the file www/templates/tab-chats.html to www/templates/tab-latest-posts.html.
  • Change chat-detail.html to post-detail.html. Also rename the file www/templates/chat-detail.html to www/templates/post-detail.html.
  • Change tab-account.html to tab-settings.html. Also rename the file www/templates/tab-account.html to www/templates/tab-settings.html.
  • Finally, change the view that gets loaded by default to latest-posts by using $urlRouterProvider.otherwise('/tab/latest-posts').

If all went well then you should end up with the www/js/app.js file looking like this:

1
...
2
// Each tab has its own nav history stack:

3
4
  .state('tab.latest-posts', {
5
      url: '/latest-posts',
6
      views: {
7
        'tab-latest-posts': {
8
          templateUrl: 'templates/tab-latest-posts.html',
9
          controller: 'LatestPostsCtrl'
10
        }
11
      }
12
    })
13
    .state('tab.post-detail', {
14
      url: '/latest-posts/:postId',
15
      views: {
16
        'tab-latest-posts': {
17
          templateUrl: 'templates/post-detail.html',
18
          controller: 'PostDetailCtrl'
19
        }
20
      }
21
    })
22
23
  .state('tab.settings', {
24
    url: '/settings',
25
    views: {
26
      'tab-settings': {
27
        templateUrl: 'templates/tab-settings.html',
28
        controller: 'SettingsCtrl'
29
      }
30
    }
31
  });
32
33
  // if none of the above states are matched, use this as the fallback

34
  $urlRouterProvider.otherwise('/tab/latest-posts');
35
  ...

And our cleaned up www/js/controllers.js file looks like this:

1
angular.module('starter.controllers', [])
2
.controller('LatestPostsCtrl', function($scope) {})
3
.controller('PostDetailCtrl', function($scope, $stateParams) {})
4
.controller('SettingsCtrl', function($scope) {});

Now that we have restructured the app to fit our needs, let's move on to the next part and add some functionality.

How to Retrieve an RSS Feed With Ionic

In order to display the list of latest posts, our application will need to retrieve the RSS feed from a URL. As a best practice, it is advisable that this kind of functionality reside in the service layer of the application. In this way we can use it more easily in our controller and then present it to the user by using a view.

The RSS service will make use of Yahoo's YQL REST API to retrieve the RSS of our website. To call on the REST API, we will use the $http provider offered by AngularJS.

Ionic services are usually defined in the www/js/services.js file, so that's where we will put ours too. The code will look like this:

1
angular.module('starter.services', [])
2
.service('RSS',function($http){
3
  var self = this;
4
  this.download = function(next){
5
    var feedUrl = "https://tutsplus.com/posts.atom";
6
    var yql_query = "select * from xml where url = '"+feedUrl+"'";
7
    var url = 'https://query.yahooapis.com/v1/public/yql?q='+encodeURIComponent(yql_query)+'&format=json&callback=JSON_CALLBACK';
8
    $http
9
      .jsonp(url)
10
      .success(function(response){
11
        if (response.query.results["feed"]){
12
          next(self.parseAtom(response.query.results));
13
        } else if (response.query.results["rss"]){
14
          next(self.parseRSS(response.query.results));
15
        } else {
16
          throw "Unknown RSS format";
17
        }
18
      })
19
      .error(function(data, status){
20
21
      });
22
  }
23
24
  this.parseAtom = function(atomFeed){
25
    var posts = [];
26
    angular.forEach(atomFeed.feed.entry,function(item,idx){
27
      var post = {
28
        id:idx,
29
        title:item.title,
30
        description:item.content.content,
31
        link:item.link.href
32
      }
33
      posts.push(post);
34
    })
35
    return posts;
36
  }
37
38
  this.parseRSS = function(rssFeed){
39
    var posts = [];
40
    angular.forEach(rssFeed.rss.channel.item,function(item,idx){
41
      var post = {
42
        id:idx,
43
        title:item.title,
44
        description:item.description,
45
        link:item.link
46
      }
47
      posts.push(post);
48
    })
49
    return posts;
50
  }
51
})

We declare the service using the service() method provided by AngularJS. We then inject Angular's $http module so we can call it in our service.

The self variable is a reference to the RSS service so that we can call it from within the service's methods. The main method of the service is the download() method, which downloads the feed information and processes it. There are two main formats used for website feeds: RSS and ATOM. For our application, we have used the feed of tutorials from Tuts+ https://tutsplus.com/posts.atom which is in ATOM format, but for completeness we have taken into account the RSS format too.

The download() method calls on the YQL API and parses the results using the parseAtom() or the parseRSS() methods depending on the type of feed. The idea here is to have the same output format which will be passed further via the callback next(). With the RSS service in place, we can move on to the controller.

Hooking the RSS Service to the Latest Posts Controller

In our www/js/controllers.js file, we need to load the RSS data and pass it to our view. To do that, we only need to modify our LatestPostsCtrl controller like this:

1
.controller('LatestPostsCtrl', function($scope, RSS) {
2
  RSS.download(function(posts){
3
    $scope.posts = posts;
4
  });
5
})

Using Angular's dependency injection mechanism, we only need to specify the $scope and RSS variables as method parameters, and it will know how to load those modules. The $scope module allows us to set variables on the model bound to the view. Any values set in the scope can be then retrieved and displayed inside the view associated with the controller.

When the view for latest posts is loaded, it will call on the LatestPostsCtrl controller, and this in turn will use the RSS service to download the feed information. The results are parsed and passed back as an array using the posts variable, which we store in the current scope.

With all that out of the way, we can now move on to the view part, displaying the list of posts retrieved from the feed.

Hooking the Latest Posts View to the Feed Data

We now need to modify our view for the latest posts. If you remember, this is configured in the www/js/app.js file via the templateUrl attribute, and it points to the www/templates/tab-latest-posts.html file.

What we will want to do is display the list of feeds. Since the feed information may contain HTML, and this will only clutter the list of latest posts, we need something to extract the text without the HTML tags from a post's content. The easiest way to do that is by defining an AngularJS filter that strips the HTML tags from text. Let's do that in www/js/services.js by adding:

1
.filter('htmlToPlaintext', function() {
2
    return function(text) {
3
      return  text ? String(text).replace(/<[^>]+>/gm, '') : '';
4
    };
5
  }
6
)

No back to our view inside the www/templates/tab-latest-posts.html file, let's modify it to look like this:

1
<ion-view view-title="Latest posts">
2
  <ion-content>
3
    <ion-list>
4
      <ion-item class="item-icon-left item-icon-right" ng-repeat="post in posts" type="item-text-wrap" href="#/tab/latest-posts/{{post.id}}">
5
        <span class="icon ion-social-rss-outline"></span>
6
        <h2>{{post.title}}</h2>
7
        <p>{{post.description | htmlToPlaintext}}</p>
8
        <i class="icon ion-chevron-right icon-accessory"></i>
9
      </ion-item>
10
    </ion-list>
11
  </ion-content>
12
</ion-view>

We are using the Ionic list UI component together with Angular's ng-repeat directive, which will iterate through the posts set on the scope of our controller. For each post entry, we will have a list item with its title and with the description stripped of HTML tags by the use of the htmlToPlaintext filter. Also note that clicking a post should take us to the detail of the post because of the href attribute set to #/tab/latest-posts/{{post.id}}. That does not work yet, but we will take care of that in the next section.

If we now run the application using ionic serve --lab, we should get something like this:

Viewing Latest PostsViewing Latest PostsViewing Latest Posts

Showing the Details of a Post

When clicking on a post in the list, we go to the post details screen of the application. Because each screen of the application has its own controller and therefore its own scope, we can't access the list of posts to display a specific post. We can call the RSS service again, but that would be inefficient.

To solve this problem, we can make use of the $rootScope directive offered by Angular. This references a scope that overarches all controllers in the application. Let's modify our LatestPostCtrl to set the posts in the $rootScope and then search for the specific post that the user clicked in the PostDetailCtrl. The resulting code in www/js/controllers.js will look like this:

1
.controller('LatestPostsCtrl', function($scope, $rootScope, RSS) {
2
  RSS.download(function(posts){
3
    $rootScope.posts = posts;
4
  });
5
})
6
7
.controller('PostDetailCtrl', function($scope,$rootScope, $stateParams) {
8
  angular.forEach($rootScope.posts,function(post){
9
    if (post.id == $stateParams.postId){
10
      $scope.post = post;
11
    }
12
  })
13
})

We simply injected $rootScope in both controllers and used it for passing posts between the two controllers. Please note that we don't need to make any changes in our latest posts view as $rootScope and $scope are both accessible in the same way from the view.

Inside the PostDetailCtrl controller, we simply search for the post with the id passed in the link clicked by the user. We do that by comparing each post ID with the value in the URL passed via the $stateParams.postId variable. If we find a match then we set the post on the scope so we can use it in our view.

Let's now adjust our post detail view www/templates/post-detail.html like this:

1
<ion-view view-title="{{post.title}}">
2
  <ion-nav-buttons side="right">
3
    <a ng-href="{{post.link}}" class="button" target="_system">
4
      Open
5
    </a>
6
  </ion-nav-buttons>
7
  <ion-content class="padding">
8
    <h1>{{post.title}}</h1>
9
    <span ng-bind-html="post.description"></span>
10
  </ion-content>
11
</ion-view>

This is what we have done in the view:

  • We have placed the title of the post in the header of the screen.
  • We have placed an "Open" button in the header on the right. This button will open the post link in an external browser because of the attribute target="_system". We have to do this because the application is already running in a browser due to Cordova. If we didn't set that attribute, the post would have opened in the same browser as the application, and then we would not have a way to return to the application.
  • We display the description of the post as HTML by using Angular's ng-bind-html directive.

While running the application, I noticed that if the post description contains images, some of them fall off the screen. This might be the case with other HTML elements like videos. We can easily fix this by adding the following CSS rule in www/css/style.css.

1
ion-content *{
2
    max-width: 100%;
3
}

If we now take a look at the application and click on one of the posts, we should see something like this:

Seeing posts for Tuts articlesSeeing posts for Tuts articlesSeeing posts for Tuts articles

And our application is almost complete. In the next section, we will take a look at implementing the settings screen.

Adding Settings for Our Ionic Application

For our settings screen, we will implement a way to indicate how many posts to display on the main screen of the application. We will store this setting in the localStorage memory, which is not erased when the application is closed. Let's edit the controllers file www/js/controllers.js and change the SettingsCtrl controller like this:

1
.controller('SettingsCtrl', function($scope,$rootScope) {
2
  $scope.settings = {
3
    maxPosts:  window.localStorage.getItem("myWebsiteOnMobile.maxPosts")
4
  };
5
6
  $scope.$watch('settings.maxPosts',function(){
7
    window.localStorage.setItem("myWebsiteOnMobile.maxPosts",$scope.settings.maxPosts);
8
    $rootScope.maxPosts = window.localStorage.getItem("myWebsiteOnMobile.maxPosts");
9
  });
10
});

Also, we need to modify the settings screen in www/templates/tab-settings.html like this:

1
<ion-view view-title="Settings">
2
  <ion-content>
3
      <div class="item item-divider item-balanced">Maximum posts</div>
4
	<ion-radio ng-model="settings.maxPosts" ng-value="null">Unlimited</ion-radio>
5
	<ion-radio ng-model="settings.maxPosts" ng-value="5">5</ion-radio>
6
	<ion-radio ng-model="settings.maxPosts" ng-value="10">10</ion-radio>
7
  </ion-content>
8
</ion-view>

The controller retrieves the setting myWebsiteOnMobile.maxPosts from the localStorage. If it does not exist, it will be null, and we will consider that there is no limit for the maximum number of posts.

We call the $scope.$watch() method to monitor changes of the settings.maxPosts variable, which is bound to the radio control in the settings screen.

With all this in place, every time we change the maximum number of posts on the settings screen, the setting will be stored in the localStorage, and it will be retrieved from there when the application restarts.

Now let's make use of this setting. This is as simple as adding this in the LatestPostsCtrl from www/js/controllers.js:

1
$rootScope.maxPosts = window.localStorage.getItem("myWebsiteOnMobile.maxPosts");

And adding a directive in the latest posts screen www/templates/tab-latest-posts.html:

1
<ion-item class="item-icon-left item-icon-right" ng-repeat="post in posts|limitTo:maxPosts" type="item-text-wrap" href="#/tab/latest-posts/{{post.id}}">

Notice the limitTo:maxPosts Angular filter. This will limit the number of posts displayed to the number taken from the localStorage. By default, this will be null, which will display all the feeds retrieved by the RSS service.

Congratulations! We now have a fully working application displaying an RSS feed.

Conclusion

In this tutorial, we have seen how to create a hybrid mobile application using the Ionic Framework and AngularJS. There is only one more thing to do: run the application on a mobile device or mobile emulator. This is very simple with Ionic. To run the application on an Android emulator, just run:

1
ionic platform add android
2
ionic run

If you want to download a premade Ionic application template for transforming any website to a mobile application, try the Website to Mobile Ionic Application Template from CodeCanyon.

An application template on CodeCanyonAn application template on CodeCanyonAn application template on CodeCanyon
Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.