If you like hybrid mobile app development you’ll fell in love with Ionic Framework, just like I did. This is not the first time I’m writing about Ionic Framework, my previous article covered a tutorial on how to combine Ionic and Cordova. This article will show you how to create your first Ionic application. I’m going to comment every step of my progression, but not in great details. In the near future, my intention is to create a series of articles covering every aspect of Ionic application creation, including everything said here.
 
 

Note: If this tutorial was helpful, need further clarification, something is not working or do you have a request for another Ionic post? Furthermore, if you don't like something about this blog, if something is bugging you, don't like how I'm doing stuff here, again leave me a comment below. I'm here to help you, I expect the same from you. Feel free to comment below, subscribe to my blog, mail me to dragan.gaic@gmail.com, or follow and mention me on twitter (@gajotres). Thanks and have a nice day!

PS. If you want my help, if possible (even if it takes you some time to do that), create a working example I can play with. Use Plunker for AngularJS based questions or jsFiddle for jQuery/jQuery Mobile based questions.


 

Code

 
I will start with a full code example, working example will come after this. I made it using Plunker (plnkr.co), and it may not work from time to time (Plunker is still a new web service mostly used for AngularJS, which makes it a perfect medium for Ionic based examples).
 
I will not make a basic Ionic application, nor should you expect something like a “Hello world” application. This is going to be a multi-page application (two pages) which uses Factory service for logic handling.
 

HTML – index.html

 
<!DOCTYPE html>
<html ng-app="starter">

<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width" />
  <title>Ionic Framework Example</title>
  <link href="//code.ionicframework.com/nightly/css/ionic.css" rel="stylesheet"/>
  <link href="index.css" rel="stylesheet"/>
  <script src="//code.ionicframework.com/nightly/js/ionic.bundle.js"></script>
  <script src="app.js"></script>
</head>

<body>
  <ion-nav-view></ion-nav-view>
</body>

</html>
 

HTML – list.html

 
<ion-header-bar class="bar bar-header bar-dark">
  <h1 class="title">Search The Movie Database</h1>
</ion-header-bar>
<ion-content>
  <label class="item item-input">
    <i class="icon ion-search placeholder-icon"></i>
    <input type="search" placeholder="Search" ng-model="movie.name" ng-change="searchMovieDB()">
  </label>
  <ion-list>
    <div class="list">

      <a ng-repeat="movie in movies" href="#/movie/{{movie.id}}" class="item item-thumbnail-left">
        <img ng-src="http://d3gtl9l2a4fn1j.cloudfront.net/t/p/w185{{movie.poster_path}}" onerror="this.src = 'https://www.ginesisnatural.com/images/no_image.jpg';">
        <h2>{{movie.original_title}}</h2>
        <h4>{{movie.release_date}}</h4>
      </a>

    </div>
  </ion-list>
</ion-content>
 

HTML – view.html

 
<ion-header-bar class="bar bar-header bar-dark">
  <h1 class="title">Movie details</h1>
</ion-header-bar>
<ion-content>
  <div class="list card">

    <div class="item item-avatar">
      <img src="http://files.softicons.com/download/object-icons/movies-icons-by-pinchodesigns/png/32x32/Movie.png">
      <h2>{{movie.original_title}}</h2>
      <p>{{movie.release_date}}</p>
    </div>

    <div class="item item-image">
      <img ng-src="http://d3gtl9l2a4fn1j.cloudfront.net/t/p/w185{{movie.poster_path}}" width="200px" />
    </div>

    <a class="item" href="#">
        Average Vote: <strong>{{movie.vote_average}}</strong> (Votes: {{movie.vote_count}})
      </a>

  </div>
</ion-content>
 

JavaScript- app.js

 
var nameApp = angular.module('starter', ['ionic']);


nameApp.factory('Movies', function($http) {
  var cachedData;

  function getData(moviename, callback) {

    var url = 'http://api.themoviedb.org/3/',
      mode = 'search/movie?query=',
      name = '&query=' + encodeURI(moviename),
      key = '&api_key=470fd2ec8853e25d2f8d86f685d2270e';

    $http.get(url + mode + key + name).success(function(data) {

      cachedData = data.results;
      callback(data.results);
    });
  }

  return {
    list: getData,
    find: function(name, callback) {
      console.log(name);
      var movie = cachedData.filter(function(entry) {
        return entry.id == name;
      })[0];
      callback(movie);
    }
  };

});


nameApp.config(function($stateProvider, $urlRouterProvider) {

  $stateProvider
    .state('list', {
      url: '/',
      templateUrl: 'list.html',
      controller: 'ListCtrl'
    })
    .state('view', {
      url: '/movie/:movieid',
      templateUrl: 'view.html',
      controller: 'ViewCtrl'
    });

  $urlRouterProvider.otherwise("/");

});

nameApp.controller('ListCtrl', function($scope, $http, Movies) {

  $scope.movie = {
    name: ''
  }

  $scope.searchMovieDB = function() {

    Movies.list($scope.movie.name, function(movies) {
      $scope.movies = movies;
    });
    
  };
});

nameApp.controller('ViewCtrl', function($scope, $http, $stateParams, Movies) {
  Movies.find($stateParams.movieid, function(movie) {
    $scope.movie = movie;
  });
});
 

CSS – index.css

 
.item-image {
  background: #000;
}

.item-image img:first-child, .item-image .list-img {
  width: 200px;
}
 

Working example

 
Working Plunker example can be found here:
 
Demo
 
Embedded example (enter a movie name in the search box, “Batman” for example):
 
Ionic Master Detail Pattern
 

Code overview

 
Like AngularJS, Ionic framework is all about MVC (or to be more precise Model–View–Whatever) so let’s discuss basic application details.
 
First thing we need to do is to initialize our application:
 
<html ng-app="starter">
 
This translates to JavaScript:
 
var demoApp = angular.module('starter', ['ionic']);
 
You can have multiple ng-app attributes in your page, they don’t need to be set to root HTML element, basically you can have multiple independent applications running on a same page. For Ionic to work properly we need to set the [‘ionic’] dependency, framework will not work without it.
 
This application will have two distinct pages, first one will act as a search page (list.html) while a second one (view.html) will act as a more details page. These pages have a parent page called index.html, Ionic routing system will dynamically load child pages depending on application navigation system (we will discuss this later). Both application pages (child pages) require a distinct controller:
 
demoApp.controller('ListCtrl', function($scope, $http, Movies) {
 
demoApp.controller('ViewCtrl', function($scope, $http, $stateParams, Movies) {
 
…Ctrl under controller name is an Angular convention. but you can give it any name. For better future readability stick to this convention. Another important thing to remember is $scope. This is Angular model, it’s just a javascript object. Each $scope will hold associated page data. As you can see you don’t need to call set or get functions if you want to change something inside a $scope (like in Backbone case), just access it like any other JavaScript object:
 
$scope.movies = movies;
 
Our first HTML page (list.html) contains only two page structures (elements), our search input and an empty list holder template. Our second page (view.html) has only one card template. This templete system is made to mimic HandlebarsJS template engine (or older {{mustache}} engine). For example this is a list holder template we are using in our example:
 
<div class="list">
 
  <a ng-repeat="movie in movies" href="#/movie/{{movie.id}}" class="item item-thumbnail-left">
    <img ng-src="http://d3gtl9l2a4fn1j.cloudfront.net/t/p/w185{{movie.poster_path}}" onerror="this.src = 'https://www.ginesisnatural.com/images/no_image.jpg';">
    <h2>{{movie.original_title}}</h2>
    <h4>{{movie.release_date}}</h4>
  </a>
 
</div>
 
{{movie.original_title}} represents object movie -> parameter original_title.
 
Now let’s talk about how this application works. First we need to write something into our search input, it looks like this:
 
<input type="search" placeholder="Search" ng-model="movie.name" ng-change="searchMovieDB()">
 
Because this input has an AngularJS attribute ng-model=”movie.name” everything we write in it will be bound to $scope object movie:
 
  $scope.movie = {
    name: ''
  }
 
Advanced note: this is where Ionic frameworks differs a bit from the vanilla AngularJS. In AngularJS case we could have used primitive variable instead of an object. Unfortunately, thanks to some Ionic framework handlings, everything found inside a tag (directive) will be part of a child scope and one of the ways for it to access main scope is for us to bind it to a main scope object (not primitive variable, it will not work in this case), in our case it is $scope.movie = {....
 
Another important thing about this input box is, each time we change something it will trigger change event bound to this input box (ng-change=”searchMovieDB()”). This event will trigger function searchMovieDB which is part of a List controller (ListCtrl):
$scope.searchMovieDB = function() {
 
This is where things get a little bit complicated. This function will call another function which is part of a factory service called Movies. This :
 
Movies.list($scope.movie.name, function(movies) {
 
will call this:
 
list: getData,
 
Continue Reading

  • Emil Rasmussen

    Hi Dragan Gaic,

    Such a nice tutorial!
    I'm trying to use a local database, and then it should do the same as this application with the data in my database,
    but I have a hard time doing that.

    Do you have any ideas, how I could do that?

    Regards,