Building AngularJS based native mobile application. Part 2

This is the second part of tutorial for building native mobile application based on AngularJS, HTML5 markup and CSS styles. In the first part you will find how to setup the new project, add routes, controllers, HTML5 views and do simple testing in a standard web browser.

What we are doing in this tutorial?

In this tutorial part we are going to take previously created application and add back navigation button, sliding animations between the views and functionality to retrieve data from web services by using asynchronous HTTP communication. Finally I’ll give some hints how to wrap this application into PhoneGap framework in order to create installable version. Lets get started.

Providing navigation buttons

Adding back button to AngularJS framework

Last time we noticed that it would be great to have navigation options for app users so they can return to the previously viewed application page.
As our example application is quite simple, adding HTML markup for navigation is a straight forward process. Ratchet (the front end framework we are using for this project) has back button styles already built in. We just have to add a link element above the title of navigation bar to TheatersControllerView.html. Adding it below would create right side navigation bar button.

<header>
  <a href="#/">Back</a>
  <h1>Find a theater</h1>
</header>

The back route we add is to the root view as there is only way app user can navigate to TheatersControllerView. Other views in our app don’t need to have navigation back option.

Adding animations to AngulaJS projects

From the version 1.1.5 AngularJS framework has inbuilt support for animated transitions for certain directives. This currently can be done in 3 ways, CSS Transitions, CSS Animations and good old JavaScript way. There is even website dedicated solely to AngularJS animations and it does a good job explaining how stuff works (this is why a great developer community supporting the framework is so useful).
We are going to use CSS Transition in this tutorial by adding ng-animate element to our HTML to let AngulaJS know we want to have CSS style animated transition. We have to provide this element with the value of our CSS animation name. While building HTML AngularJS will attach 2 CSS classes to the DOM element named according to the animation name we gave earlier. Given that our animation name is slide the classes added by AngularJS will be slide-enter and slide-enter-active. Its possible to provide custom names for CSS classes as well. You would do it like this

ng-animate="{enter: 'slide-begin', leave: 'slide-exit'}"

Lets add simple CSS class code and ng-animate element to our projects index.html root file after which the file content should look like this

<!DOCTYPE html>
<html data-ng-app="pomidoroApp">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no">
    <link rel="stylesheet" href="css/ratchet.css">
    <link rel="stylesheet" href="css/app.css">
  </head>
  <body>
    <style type="text/css">
      /* Angular.js animated navigation */
      .slide-enter,
      .slide-leave
      {
        -webkit-transition: 300ms cubic-bezier(0.075, 0.820, 0.165, 1.000) all;
        -moz-transition: 300ms cubic-bezier(0.075, 0.820, 0.165, 1.000) all;
        -ms-transition: 300ms cubic-bezier(0.075, 0.820, 0.165, 1.000) all;
        -o-transition: 300ms cubic-bezier(0.075, 0.820, 0.165, 1.000) all;
        transition: 300ms cubic-bezier(0.075, 0.820, 0.165, 1.000) all;
      }  
      .slide-enter {
        left: 100%;
      }
      .slide-enter.slide-enter-active {
        left: 0px;
      }      
      .slide-leave {}
      .slide-leave.slide-leave-active{
      left: -200px;
      }
    </style>
    <!-- placeholder for view markup -->
    <div ng-view ng-animate="'slide'"></div>  
    <script src="js/angular.min.js"></script>
    <script src="js/app.js"></script>
  </body>
</html>

Now after testing the project code in Safari browser we can see a nice navigation effect after the particular movie from the list is clicked by user. This animation transitions us to the theaters controller and view. After testing on mobile devices I noticed that sliding effect is a little bit slow and has small lag as well. How to smooth it up is not the goal of this tutorial and most likely I’ll cover this subject in the separate post here on HTML Center. Next chapter is about adding web services communication functionality to consume Rotten Tomatoes API data and display it in our app.

Adding HTTP communication to AngularJS app

Building mobile application with Rotten Tomatoes API

For performing HTTP requests AngularJS has a property named $http (nice and simple naming). It also has strong support for promises. Promises (if you are not so much familiar with them) is a concept we use while dealing with async communication requests. Then we perform request and assign result of that request to some variable but do not expect it to have complete response right away. Because communication with 3rd party web service takes time. Therefore promise variables are guaranteed to have response data some time in the future.

In the previous tutorial part I have mentioned that we will be using Rotten Tomatoes API for retrieving movie data. Their API for developers is both simple and provides useful movie data. Simply go and register your own developer account with them to receive API key. It’s quite a straight forward process. Once you have API credentials the simple query to Rotten Tomatoes web service in order to get 5 hot movies currently shown in UK theaters is performed like HTTP Get request with the following string

http://api.rottentomatoes.com/api/public/v1.0/lists/movies/in_theaters.json?page_limit=5&page=1&country=uk&apikey=YOUR.API.KEY

It is a good information security practice not to store your sensitive developer credentials data in app itself. As all applications are running on devices which you have completely no control off. Always try to perform communication with 3rd party API’s via back end code and keep mobile application as a simple client.

This approach will also help while dealing with Cross Origin Resource Sharing issues as JavaScript and Ajax HTTP communication needs extra attention to stay secure. On your backed you can configure CORS settings for specific requests origins etc. I have prepared very simple php based backed file which will only make a request to Rotten Tomatoes API and return all result data back to our mobile app

<?php

// Simple tweak to allow access from any origin
// Credits to http://stackoverflow.com/questions/8719276/cors-with-php-headers
//
if (isset($_SERVER['HTTP_ORIGIN'])) {
    header("Access-Control-Allow-Origin: {$_SERVER['HTTP_ORIGIN']}");
    header('Access-Control-Allow-Credentials: true');
    header('Access-Control-Max-Age: 86400');    // cache for 1 day
}

// Access-Control headers are received during OPTIONS requests
if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {

    if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD']))
        header("Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS");         

    if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']))
        header("Access-Control-Allow-Headers: {$_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']}");
}

///////////////////////////////////////
// SETUP //////////////////////////////
///////////////////////////////////////

// API credentials
//
$apikey = "YOUR ROTTEN TOMATOES API KEY";

// Number of items in response 
$returnitems = 5;

$url = "http://api.rottentomatoes.com/api/public/v1.0/lists/movies/in_theaters.json?page_limit=".$returnitems."&page=1&country=uk&apikey=".$apikey;

// Building string for GET request
//
$requeststr = $url;

// CURL for communicating with web service
//
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,$requeststr);
curl_setopt($ch, CURLOPT_VERBOSE, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);

$response = curl_exec($ch);
echo $response;
?>

You will notice at the beginning of the file I have code to enable cross domain access for Ajax requests. You can limit this to specific origin, domain etc.

We will now update our factory and replace static and hard coded data we previously had with the $http.get request. $http is the service available to your applications if it uses AngularJS framework and is in detail described in official documentation.  As we already discussed all HTTP communication is asynchronous and this means we have to handle the scenario where requested data is not right away available for our controller and the view. We add the following code to the factory method to recommendedMoviesFactory

// This is the place for performing http communication
// with 3rd party web services.
var url = 'your.backend.url'

return $http.get(url).then( function(response){
  return response.data;
})

Now in the RootControler we are handling the fact that data coming from $http can be delayed by adding ready flag to the $scope element. This will let us display HTML elements in the view only once all the data is received from Rotten Tomatoes API

// RootController
//
pomidoroApp.controller('RootController', function($scope,recommendedMoviesFactory){

    // Controller is going to set recommendedMovies
    // variable for the $scope object in order for view to
    // display its contents on the screen as html 
    $scope.recommendedMovies = [];

    // Just a housekeeping.
    // In the init method we are declaring all the
    // neccesarry settings and assignments
    init();

    function init(){

        // As we need to wait for $http.get 
        // request data to be ready we are 
        // using .then on the promisse received
        // from factory
        recommendedMoviesFactory.getRecommended().then(function(data) {
           //this will execute when the 
           //AJAX call completes.
           $scope.recommendedMovies = data.movies;
           $scope.ready = true;           
           console.log(data.movies);
        });
    };

});

What’s left is to update the RootControlerView with the the information about new elements in the data provided by controller (notice in previous code example, I’m using console.log() to print out and investigate all the available JSON data structure supplied by Rotten Tomatoes API) and add a filter in order to filter list of 5 movies with the search input field. Here is the updated version of this file

<div>
  <ul>
    <li>Recommended movies</li>
    <li ng-show="!ready">
      Receiving data...
    </li>
    <li ng-show="ready" ng-repeat="movie in recommendedMovies | filter:name">
      <a href="#/theaters">
        <div>
         <img style="float:left; width:120px; height:177px; margin-right:10px;"class="movieimg" src="{{movie.posters.profile}}" />
         <strong style="font-size:18px;">{{movie.title}}</strong>
         <p style="font-size:16px;">{{movie.critics_consensus}}</p>
        </div>
        <div style="clear:both;"></div>   
      </a>
    </li>
  </ul>
</div>

In the above code I’m making use of ready variable which is being set in controller and will be set to yes once all requested movie data is available. Until then I’m going to display "Receiving data..." text in the list item element. ng-show is the directive making this all happen as I only have to supply ng-show="!ready" and AngularJS knows to hide it once variable is being set to true.

Now once project files are updated, reloading the page will give us the following result. By no means its a finished mobile application but it has a good foundations and MVC framework to build on to. But it has scroll view, dynamically loading content from external web services, animated transitions and is powered by AngularJS.

Building mobile application with AngularJS

Testing AngularJS project with PhoneGap

As we were working in the directory called www migrating this project to wraper like PhoneGap and make it installable app is quite easy. You just have to replace contents of the www directory in your PhoneGap XCode project with the ones you created during this tutorial. If you want to understand how to create PhoneGap powered XCode application we have good tutorial for your here at HTML Center.

I hope you have enjoyed this tutorial, final source code for example application can be found hosted on the GitHub. As always I welcome all the comments, suggestions and advice.

5 Responses

  • Flex11

    Hey. This is quite useful and informative article.

  • Shijin Krishna

    I just tried with keeping a basic php file in www folder and added below lines

    <?php

    echo "Hello Singapore!";

    now in my index.php file I added the below code

    {{response}}

    var app = angular.module(‘myApp’, []);

    app.controller(‘customersCtrl’, function($scope, $http) {

    $http.get(“serverside/data.php”)

    .success(function (response) {

    $scope.response = response;

    //alert(response)

    });

    });

    after installing the app its just showing

    <?php

    echo "Hello Singapore!";

    instead of printing only Hello Singapore.

    Please suggest something.

    Thanks in advance

    • hey, looks like your server is not running php or is not executing php index files. get in touch with your hosting provider.

  • Amar Bhanu

    how to convert into .apk this code, if you know then suggest