Building a Hybrid Mobile app using Ionic Framework

Getting started with Ionic Framework. This tutorial show you how to do simple CRUD operation using Ionic Framework. What you need for this tutorial are

Outline that cover for this tutorial:

  • Set up your development environment
  • Preview your app
  • Learn client side API
  • Build a multi page application
  • Integration with server side API

Setting up your development environment

After that, install node.js to use npm for package manager. If you not install node.js, you should not be able to invoke node or npm on your command line to install Ionic Framework. Then install Ionic Framework using terminal or command prompt.

npm install -g cordova ionic

After you finish install the Ionic Framework. You can start create your project using Ionic command. Open your terminal/command prompt, type these command.

ionic start IonicToDoList tabs
ionic start IonicToDoList tabs

ionic start IonicToDoList tabs

Open Ionic project with Sublime.

Ionic project with Sublime Text

Ionic project with Sublime Text

Open config.xml and replace with this id.

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<widget id="com.ionicframework.ionictodolist" version="0.0.1" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
  <name>IonicToDoList</name>
  <description>
        An Ionic Framework and Cordova project.
    </description>
  <author email="you@example.com" href="http://example.com.com/">
      Your Name Here
    </author>
  <content src="index.html"/>
  <access origin="*"/>
  <preference name="webviewbounce" value="false"/>
  <preference name="UIWebViewBounce" value="false"/>
  <preference name="DisallowOverscroll" value="true"/>
  <preference name="SplashScreenDelay" value="2000"/>
  <preference name="FadeSplashScreenDuration" value="2000"/>
  <preference name="android-minSdkVersion" value="16"/>
  <preference name="BackupWebStorage" value="none"/>
  <preference name="SplashScreen" value="screen"/>
  <feature name="StatusBar">
    <param name="ios-package" value="CDVStatusBar" onload="true"/>
  </feature>
</widget>

Build android and iOS app using this command.

cd IonicToDoList
ionic platform add android
ionic platform add ios
sudo ionic platform add android

sudo ionic platform add android

Preview your app (android)

Open your eclipse. Select File > Import.

import android project

import android project

Select Existing Android Code Into Workspace. Click Next.

import android project

import android project

Click Browse to select android project and click Finish.

import android project

import android project

Run android app in android simulator.

Preview your app (iOS)

Open your Xcode. Right click on iphone folder and go to Run AsXcode Project.

Xcode

Xcode

Open app.js file in www/js folder. Replace with this code.

angular.module('starter', ['ionic', 'starter.controllers', 'starter.services'])

.run(function($ionicPlatform) {
  $ionicPlatform.ready(function() {
    if (window.cordova &amp;&amp; window.cordova.plugins &amp;&amp; window.cordova.plugins.Keyboard) {
      cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
      cordova.plugins.Keyboard.disableScroll(true);

    }
    if (window.StatusBar) {
      StatusBar.styleDefault();
    }
  });
})

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

    .state('tab', {
    url: '/tab',
    abstract: true,
    templateUrl: 'templates/tabs.html'
  })

  .state('tab.list', {
      url: '/list',
      views: {
        'tab-list': {
          templateUrl: 'templates/list.html',
          controller: 'ListCtrl'
        }
      }
    })
    .state('tab.detail', {
      url: '/detail/:taskId',
      views: {
        'tab-detail': {
          templateUrl: 'templates/detail.html',
          controller: 'DetailCtrl'
        }
      }
    })

  .state('tab.add', {
    url: '/add',
    views: {
      'tab-add': {
        templateUrl: 'templates/add.html',
        controller: 'AddCtrl'
      }
    }
  });

  $urlRouterProvider.otherwise('/tab/list');

})

.directive("initFromForm", function ($parse) {
    return {
        link: function (scope, element, attrs) {
            var attr = attrs.initFromForm || attrs.ngModel || element.attrs('name'),
            val = attrs.value;
            $parse(attr).assign(scope, val);
        }
    };
});

Open services.js file in www/js folder. Replace with this code.

angular.module('starter.services', [])

.factory('todoService', function($http) {
    var baseUrl = 'http://demo.revivalx.com/todolist-api/';
    return {
        getAll: function() {
            return $http.get(baseUrl+'get_all_tasks.php');
        },
        getId: function (taskId){
            return $http.get(baseUrl+'get_task_details.php?taskId='+taskId); 
        },
        create: function (data){
            return $http.post(baseUrl+'create_task.php',data,{
                headers: {
                    'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8;'
                }
            });
        },
        update: function (data){
            return $http.post(baseUrl+'update_task.php',data,{
                headers: {
                    'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8;'
                }
            });
        },
        delete: function  (taskId){
            return $http.get(baseUrl+'delete_task.php?id='+taskId);
        }
    };
    
});

Open controllers.js file in www/js folder. Replace with this code.

angular.module('starter.controllers', [])

.controller('tabCtrl', function($scope){
})

.controller('ListCtrl', function($scope,$state, todoService){
    $scope.showData = function() {
      todoService.getAll().success(function(data) {
            $scope.datatodos = data;
        }).finally(function() {
            $scope.$broadcast('scroll.refreshComplete');
        });
    };
    $scope.showData();
    
    $scope.reload = function (){
        $state.go('tab.list');
    };
    
    $scope.delete = function (datatodo){
        todoService.delete(datatodo.taskId);
        $scope.datatodos.splice($scope.datatodos.indexOf(datatodo),1);
    };
})

.controller('AddCtrl', function($scope,$ionicPopup,todoService){
    $scope.showAlert = function(msg) {
      $ionicPopup.alert({
          title: msg.title,
          template: msg.message,
          okText: 'Ok',
          okType: 'button-positive'
      });
    };
    
    $scope.datatodo={};
    $scope.save = function (){
        if (!$scope.datatodo.name){
            $scope.showAlert({
                title: "Information",
                message: "Name is required"
            });
        }else if (!$scope.datatodo.description){
            $scope.showAlert({
                title: "Information",
                message: "Description is required"
            });
        }else{
            todoService.create({
                name: $scope.datatodo.name,
                description: $scope.datatodo.description,
            }).success(function(data){
                $scope.showAlert({
                    title: "Information",
                    message: "Successfully recorded"
                });
            });
        }
        
    };
       
})

.controller('DetailCtrl', function($scope,$stateParams,$ionicPopup,$ionicModal,$state,todoService){
        
    $scope.showDataId = function() {
      todoService.getId($stateParams.taskId).success(function(datatodo) {
            $scope.datatodo = datatodo;
        });
        
    };
    $scope.showDataId();
    
    $scope.back = function (){
        $state.go('tab.list');
    };
    
    $ionicModal.fromTemplateUrl('edit.html', function(modal){
        $scope.taskModal = modal;
  }, {
            scope : $scope,
            animation : 'slide-in-up' 
  });
        
        $scope.showAlert = function(msg) {
            $ionicPopup.alert({
                title: msg.title,
                template: msg.message,
                okText: 'Ok',
                okType: 'button-positive'
            });
          };
  
  $scope.editModal = function(){
            $scope.taskModal.show();
  };
  
  $scope.cancel = function(){
            $scope.taskModal.hide();
            $scope.showDataId();
  };
        
  $scope.edit = function(taskId,name,description){
            if (!taskId){
                $scope.showAlert({
                    title: "Information",
                    message: "Id is required"
                });
            }else if (!name){
                $scope.showAlert({
                    title: "Information",
                    message: "Name is required"
                });
            }else if(!description){
                $scope.showAlert({
                    title: "Information",
                    message: "Description is required"
                });
            }else{
                $scope.id = id;
                $scope.name = name;
                $scope.description = description;
                todoService.update({
                    'id' : id,
                    'name': name,
                    'description': description,
                }).then(function(resp) {
                  console.log('Success', resp);
                  $scope.showAlert({
                        title: "Information",
                        message: "Successfully updated"
                    });
                },function(err) {
                  console.error('Error', err);
                }); 
            }
  };
  
});

Delete all the html files in www/templates and create these all 4 files.

  1. add.html.
  2. detail.html.
  3. list.html.
  4. tabs.html.

Replace all codes with given codes for each html files.

tabs.html

<ion-tabs class="tabs-icon-top tabs-color-active-positive">

  <ion-tab title="Status" icon-off="ios-list" icon-on="ion-ios-pulse-strong" href="#/tab/list">
    <ion-nav-view name="tab-list"></ion-nav-view>
  </ion-tab>

  <ion-tab title="Status" icon-off="ios-add" icon-on="ion-ios-pulse-strong" href="#/tab/add">
    <ion-nav-view name="tab-add"></ion-nav-view>
  </ion-tab>

</ion-tabs>

list.html

<ion-header-bar class="bar-positive">
        <button class="button button-icon icon ion-ios7-minus-outline" ng-click="data.showDelete = 
        !data.showDelete; data.showReorder=false"></button>
        <h1 class="title">ToDo List</h1>
        <button class="button button-icon icon ion-ios7-loop" ng-click="reload()"></button>
</ion-header-bar>
<ion-view>
    <ion-content padding="false" class="has-header">
        <ion-refresher
            pulling-text="Pull to refresh..."
            on-refresh="showData()">
          </ion-refresher>
        <ion-list show-Delete = "data.showDelete" show-Reorder = "data.showReorder">
            <ion-item class="item-avatar item-icon-right" ng-repeat="datatodo in datatodos" type="item-text-wrap" href="#/tab/detail/{{datatodo.taskId}}">
                <i class="icon ion-ios7-arrow-right"></i>
                <h2>{{datatodo.name}}
                    <br> 
                    <font size="2" color="gray" >Description : {{datatodo.description}}</font>
                </h2>
                <ion-delete-button class="ion-minus-circled" ng-click="delete(datatodo);"></ion-delete-button>
            </ion-item>
        </ion-list>
    </ion-content>
</ion-view>

add.html

<ion-header-bar class="bar-positive">
        <h1 class="title">Add Task</h1>
</ion-header-bar>
<ion-content class="padding">
      <form>
        <ion-list>
            <label class="item item-input">
                <input type="text" ng-model="datatodo.name" placeholder="Name">
            </label>
            <label class="item item-input">
                <input type="text" ng-model="datatodo.description" placeholder="Description">
            </label>
        </ion-list>
        <div class="spacer" style="height: 5px;"></div>
        <button class="button icon ion-person-stalker button-balanced button-block" ng-click="save();"> Save</button>
    </form>
</ion-content>

detail.html

<ion-header-bar class="bar-positive">
        <button class="button button-icon icon ion-ios7-arrow-left" ng-click="back();">Back</button>
        <h1 class="title">Task Detail</h1>
</ion-header-bar>
<ion-content class="padding" ng-repeat="datatodo in datatodo">
    <h3>Detail :</h3>
    <p>
        <font size="2" color="gray" >Nama : {{datatodo.name}}</font>
    <br>
        <font size="2" color="gray" >Description : {{datatodo.description}}</font>
    </p>
    <button class="button button-balanced button-block" ng-click="editModal()">Edit Task</button>
</ion-content>
<script id="edit.html" type="text/ng-template">
        <div class="modal">
            <ion-header-bar class="bar-stable">
                <button class="button button-icon icon ion-ios7-close-outline" ng-click="cancel()"></button>
                <h1 class="title"> Edit Task</h1>
            </ion-header-bar>
            <ion-content ng-repeat="datatodo in datatodo">
                <form>
                    <div class="list">
                        <label class="item item-input">
                        <span class="input-label">ID :</span>
                            <input type="text" placeholder="{{datatodo.taskId}}" ng-model="id" value="{{datatodo.id}}" init-from-form>
                            <p>{{datatodo.taskId}}</p>
                        </label>
                        <label class="item item-input">
                        <span class="input-label">Name :</span>
                            <input type="text" placeholder="{{datatodo.name}}" ng-model="name" value="{{datatodo.name}}" init-from-form>
                        </label>
                        <label class="item item-input">
                        <span class="input-label">Description :</span>
                            <input type="text" placeholder="{{datatodo.description}}" ng-model="description" value="{{datatodo.description}}" init-from-form>
                        </label>
                        <button class="button button-positive button-block" ng-click="edit(taskId,name,description);">
                            Save
                        </button>
                    </div>
                </form>
        </ion-content>
        </div>
</script>

Build your project using this command and run the app.

ionic build ios
ionic build android

Leave a Reply

Your email address will not be published. Required fields are marked *