Creating your first Ionic Framework application

Written by on April 7, 2015

Creating your first Ionic Framework application

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, you need further clarification, something is not working or you have a request for another Ionic post? Furthermore, leave me a comment below if you don't like something about this blog, if something is bugging you, don't like how I'm doing stuff here. Feel free to comment below, subscribe to my blog, mail me to dragan.gaic@gmail.com. Thanks and have a nice day!

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

Categories

1 thought on “Creating your first Ionic Framework application”

  1. 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,

Leave a Reply