modev-ionic



modev-ionic

0 0


modev-ionic


On Github withinsight / modev-ionic

Building Hybrid Apps with AngularJS and Ionic

Overview

Why Ionic? Ionic Technology Stack Ionic Components Angular Shallow Dive Building out a Demo Application Access Native Device Functionality AngularJS Primer
“I want to build an app!”

More Platforms. More Problems.

  • Proficiency in each platform required
  • Entirely separate code bases
  • Timely & expensive development
  • Diminishing returns

Hybrid Apps!

HTML5 that acts like native

Web wrapped in native layer

Direct access to native APIs

Familiar web dev environment

A single code base (web platform!)

“It's not 2007 anymore”
Year Device Processor RAM 2007 iPhone 400 MHz 128 MB 2010 iPhone 4 1 GHz 512 MB 2015 iPhone 6 1.4 GHz dual-core 1 GB

Web Technologies You Already

Know & Love

(You'll feel right at home)

States Managed by UI Router

angular.module('ionicApp', ['ionic'])

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

  .state('app', {
    url: '/app',
    abstract: true,
    templateUrl: 'templates/menu.html',
    controller: 'AppCtrl'
  })

  .state('app.search', {
    url: '/search',
    views: {
      'menuContent': {
        templateUrl: 'templates/search.html'
      }
    },
  })

  .state('app.browse', {
    url: '/browse',
    views: {
      'menuContent': {
        templateUrl: 'templates/browse.html',
        controller: 'BrowseCtrl'
      }
    },
  })

  $urlRouterProvider.otherwise('/app/browse');
});
        

State-Based Router with Nested Views

Your own Components

<div class="list card">
  <div class="item item-body card-body">
    <div class="image-container">
      <img src="{{postData.image}}" alt="" />
    </div>
    <div class="content-container">
      <div class="description">{{postData.description}}</div>
      <div class="" ng-if="postData.comments.length">
        <button class="button button-clear button-positive" ng-click="toggleComments()">
          ...
        </button>
        <div class="item item-text-wrap" ng-show="commentsVisible" ng-repeat="comment in postData.comments track by $index">
          {{comment}}
        </div>
      </div>
      <div ng-show="commentFieldVisible">
        <div class="item item-input-inset" ng-show="commentFieldVisible">
          <label class="item-input-wrapper">
            <input type="text" placeholder="Add a comment" ng-model="newComment">
          </label>
          <button class="button button-small button-balanced" ng-click="addComment()">Submit</button>
        </div>
      </div>
      <div class="button-bar">
        ...
      </div>
    </div>
  </div>
</div>
        

It's just Angular.js! (No extra learning curve)

.directive('postCard', function() {
  return {
      restrict: 'E',
      templateUrl: 'templates/post-card.html',
      scope: {
        postData: "=",
      },
      controller: function($scope, $element) {
        // Some controller logic
      }
  };
});
.controller('BrowseCtrl', function($scope) {
  $scope.posts = [
    { image: 'img/arya.jpg', description: "" },
    { image: 'img/jon-snow.jpg', description: "" },
    { image: 'img/tyrion.jpg', description: "" },
    { image: 'img/daenerys.jpg', description: "" },
  ];
})
        
  ...
  <ion-content>
    <post-card ng-repeat="post in posts" post-data="post"></post-card>
  </ion-content>
  ...
        

Required Tools

  • NodeJS (https://nodejs.org/en/)
  • Bower (http://bower.io/#install-bower)
  • Ionic & Cordova (http://ionicframework.com/docs/guide/installation.html)

npm install -g ionic cordova

Boilerplate app structure ready for customization

LiveReload both local and native builds

Build and run native apps

Helpful Ionic CLI Commands

  • ionic setup sass
  • ionic serve (browser)
  • ionic serve -l (launches Lab)
  • If you have platform tools installed (iOS & Android SDKs):
    • ionic emulate (Ionic adds iOS platform and builds for iOS by default)
    • To build & run using Android SDK:
      • ionic platform add android
      • ionic build android
      • ionic run android

Building out our app

js/app.js
angular.module('ionicApp', ['ionic'])

.config(function($stateProvider, $urlRouterProvider) {
  $stateProvider
  .state('app', {
    url: '/app',
    abstract: true,
    templateUrl: 'templates/menu.html',
    controller: 'AppCtrl'
  })

  .state('app.browse', {
    url: '/browse',
    views: {
      'menuContent': {
        templateUrl: 'templates/browse.html',
        controller: 'BrowseCtrl'
      }
    },
  });
  // if none of the above states are matched, use this as the fallback
  $urlRouterProvider.otherwise('/app/browse');
})

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

.controller('BrowseCtrl', function($scope) {});


                        
/templates/browse.html
<ion-view view-title="Browse">
  <ion-content>
    <h2>Browse</h2>
  </ion-content>
</ion-view>
            
/templates/menu.html
<ion-side-menus enable-menu-with-back-views="false">
  <ion-side-menu-content>
    <ion-nav-bar class="bar-positive">
      <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-content>
      <ion-list>
        <ion-item menu-close href="#/app/browse">
          Browse
        </ion-item>
      </ion-list>
    </ion-content>
  </ion-side-menu>
</ion-side-menus>
            

Managing and Abstracting our view logic

/templates/post-card.html
<div class="list card">
  <div class="item item-body card-body">
    <div class="image-container">
      <img src="{{postData.image}}" alt="" />
    </div>
    <div class="content-container">
      <div class="description">{{postData.description}}</div>
      <div class="" ng-if="postData.comments.length">
        <button class="button button-clear button-positive" ng-click="toggleComments()">
          ...
        </button>
        <div class="item item-text-wrap" ng-show="commentsVisible" ng-repeat="comment in postData.comments track by $index">
          {{comment}}
        </div>
      </div>
      <div ng-show="commentFieldVisible">
        <div class="item item-input-inset" ng-show="commentFieldVisible">
          <label class="item-input-wrapper">
            <input type="text" placeholder="Add a comment" ng-model="newComment">
          </label>
          <button class="button button-small button-balanced" ng-click="addComment()">Submit</button>
        </div>
      </div>
      <div class="button-bar">
        ...
      </div>
    </div>
  </div>
</div>
                        
/js/app.js
.controller('BrowseCtrl', function($scope) {
  $scope.posts = [
    { image: 'img/arya.jpg', description: "..." },
    { image: 'img/jon-snow.jpg', description: "..." },
    { image: 'img/tyrion.jpg', description: "..." },
    { image: 'img/daenerys.jpg', description: "..." },
  ];
})
            
/templates/browse.html
<ion-view view-title="Browse">
  <ion-content class="animate-fade-slide-in">
    <post-card ng-repeat="p in posts" post-data="p"></post-card>
  </ion-content>
</ion-view>
            
/js/app.js
.directive('postCard', function($ionicActionSheet, $ionicPopup, $timeout) {
    return {
        restrict: 'E',
        templateUrl: 'templates/post-card.html',
        scope: {
          postData: "=",
        },
        controller: function($scope, $element) {
          $scope.commentsVisible = false;
          $scope.commentFieldVisible = false;
          $scope.postData.comments = $scope.postData.comments || [];

          $scope.toggleLike = function() { ...

          $scope.addComment = function() { ...

          $scope.showOptions = function() { ...

        }
    };
});
            

Accessing and Managing our Server Side Data

Providers and Service Objects

js/app.js
.factory('Post', function($resource) {
  return $resource('http://my-awesome-REST-API.com/post');
})
                        
js/app.js
.controller('BrowseCtrl', function($scope, Post) {
  // Get all posts
  $scope.posts = Post.query();
})
                        
1. Install ngResource via Bower (optional)
  $ bower install ng-resource --save
            
2. Add dependency to index.html (optional)
 <script src="lib/ng-resource/<path to>/ng-resource.js"></script>
            
3. Include in Angular app dependencies (optional)
 angular.module('ionicApp', ['ionic', 'ngResource'])
            
AdMob Device Keychain Social Sharing App Availability Device Motion NativeAudio Spinner BackgroundGeolocation Device Orientation Media Splashscreen Battery Status Dialogs Local Notification SQLite Barcode Scanner File Network Statusbar Camera Flashlight OAuth Toast Capture Geolocation Pin Dialog Touch ID Clipboard Globalization Printer Vibration Contacts GoogleAnalytics Progress Indicator Zip DatePicker Keyboard Push Notifications More...

Access Native Device Functionality

  • Install ngCordova
  • Include ngCordova JS in index.html (after bundled ionic/angularjs)
  • Inject ngCordova service
  • Install the Cordova Camera plugin

bower install ngCordova --save-dev

lib/ngCordova/dist/ng-cordova.js

angular.module('starter', ['ionic','ngCordova'])

ionic plugin add org.apache.cordova.camera

ngCordova Example

.controller('AppCtrl', function($scope, $cordovaCamera) {

  document.addEventListener("deviceready", function () {

    var options = {
      quality: 50,
      destinationType: Camera.DestinationType.DATA_URL,
      sourceType: Camera.PictureSourceType.CAMERA,
      allowEdit: true,
      encodingType: Camera.EncodingType.JPEG,
      targetWidth: 100,
      targetHeight: 100,
      popoverOptions: CameraPopoverOptions,
      saveToPhotoAlbum: false,
      correctOrientation:true
    };

    $scope.getPicture = function() {
      $cordovaCamera.getPicture(options).then(function(imageData) {
        var image = document.getElementById('myImage');
        image.src = "data:image/jpeg;base64," + imageData;
      }, function(err) {
        // error
      });
    };

  }, false);
});
        
<ion-nav-buttons side="right">
  <button class="button button-icon button-clear ion-plus"
          menu-toggle="right"
          ng-click="getPicture()"></button>
</ion-nav-buttons>
        

Taking a photo

Coming Soon...

Get Started with Ionic!

Getting started guide ionicframework.com/getting-started

Documentation ionicframework.com/docs

Visit the Community Forum forum.ionicframework.com

Contribute on GitHub github.com/driftyco/ionic

</html>

@mobomoapps

http://withinsight.github.io/modev-ionic

Building Hybrid Apps with AngularJS and Ionic