Wiki

Clone wiki

asd-2016 / Lecture11a

Installing Ionic

Ionic is a framework built on top of AngularJS that can be used to build hybrid mobile applications. Ionic relies on Cordova for accessing the system services (e.g. camera, geolocalization, etc) on the mobile device.

Let us start by installing the framework into our computer. In a terminal, execute the following commands:

npm install -g cordova ionic
ionic start myApp sidemenu
cd myApp
ionic serve --nolivereload

Changing the demo application

Let us have a look into the initialization code (file www/js/app.js).

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

app.run(function($ionicPlatform) {
  $ionicPlatform.ready(function() {
    if (window.cordova && window.cordova.plugins.Keyboard) {
      cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
      cordova.plugins.Keyboard.disableScroll(true);
    }
    if (window.StatusBar) {
      StatusBar.styleDefault();
    }
  });
});

app.config(function($stateProvider, $urlRouterProvider) {
  $stateProvider
    .state('bookings', {
      url: '/bookings',
      abstract: true,
      templateUrl: 'templates/menu.html',
      controller: 'BookingsCtrl'
    })
    .state('bookings.new', {
      url: '/new',
      views: {
        'menuContent': {
          templateUrl: 'templates/bookings/new.html'
        }
      }
    });
  $urlRouterProvider.otherwise('/bookings/new');
});

As any other application, the bootstrap process can take a little while. As we have already mentioned, in case of code dependencies (as it is our case, when we need to load Javascript libraries such as Google maps, Pusher, etc.), it is important to wait until all of them are properly loaded. In fact, the call to $ionicPlatform.ready() will block the application until all the libraries are loaded, ensuring that we are initializing stuff such as the connection to Pusher, with the correct values (otherwise we will be calling undefined functions).

The second part of the code corresponds to the initialization of the routes. You will notice that the code is slightly different as the one we used before. It turns out that Ionic uses a different route manager (AngularUI's router) than the standard one. The main difference is that states are hierarchically such that sibling states can share common resources (e.g. same Controller, same outer template, etc.), most of them defined at the level of the parents.

Let us now have a look at the controller (file www/js/controllers.js).

var app = angular.module('starter.controllers', []);

app.controller('BookingsCtrl', function($scope, $ionicModal, $http) {
  $scope.longitude = 0;
  $scope.latitude = 0;
  $scope.sync_notification = '';

  $scope.submit = function() {
    $http.post('http://localhost:3000/bookings', {longitude: $scope.longitude, latitude: $scope.latitude})
      .then(function (response) {
        $scope.sync_notification = response.data.message;
        $scope.modal.show();
      });
  };

  $ionicModal.fromTemplateUrl('templates/bookings/sync-notification.html', {
    scope: $scope
  }).then(function(modal) {
    $scope.modal = modal;
  });

  $scope.closeModal = function() {
    $scope.sync_notification = '';
    $scope.modal.hide();
  };
});

You will notice that I dropped the use of BookingService that we were using in the previous session. I decided to introduce to you Angular's service $http, which a lower level service that you can use to implement HTTP based interactions.

Another addition is the use of modals for presenting the notifications to the end user. A modal is dialog window that is usually overlaid on top the the main window, usually with a nice animation effect. I have to say that Ionic has made a nice work to integrate modals into applications, when we compare the code required by other options. Enjoy!

Finally, let me add the HTML code for our views:

<!-- templates/menu.html -->

<ion-side-menus enable-menu-with-back-views="false">
  <ion-side-menu-content>
    <ion-nav-bar class="bar-stable">
      <ion-nav-back-button>
      </ion-nav-back-button>

      <ion-nav-buttons side="left">
        <button class="button button-icon button-clear ion-navicon" menu-toggle="left">
        </button>
      </ion-nav-buttons>
    </ion-nav-bar>
    <ion-nav-view name="menuContent"></ion-nav-view>
  </ion-side-menu-content>

  <ion-side-menu side="left">
    <ion-header-bar class="bar-stable">
      <h1 class="title">Left menu</h1>
    </ion-header-bar>
    <ion-content>
      <ion-list>
        <ion-item menu-close href="#/bookings/new">
          New booking
        </ion-item>
      </ion-list>
    </ion-content>
  </ion-side-menu>
</ion-side-menus>
<!-- templates/bookings/new.html -->

<ion-view title="New booking">
    <ion-content padding="true" class="has-header">
        <form>
            <label class="item item-input">
                <span class="input-label">Name</span>
                <input type="text" placeholder="">
            </label>
            <label class="item item-input">
                <span class="input-label">Latitude</span>
                <input type="number" placeholder="">
            </label>
            <label class="item item-input">
                <span class="input-label">Longitude</span>
                <input type="number" placeholder="">
            </label>
            <button class="button button-stable button-block " ng-click="submit()">Submit booking request!</button>
        </form>
    </ion-content>
</ion-view>
<!-- templates/bookings/sync-notification.html -->

<ion-modal-view on-double-tap="closeModal()">
  <ion-header-bar class="bar-stable">
        <div class="buttons">
            <button class="button button-stable button-clear " ng-click="closeModal()">Close</button>
        </div>
    </ion-header-bar>
    <ion-content padding="true" scroll="false" class="has-header">
        <ion-list>
            <ion-item>{{sync_notification}}</ion-item>
        </ion-list>
    </ion-content>
</ion-modal-view>

Updated