Anthanh Pham Trinh - @antaipt

MOBILE USAGE STATUS QUO

MOBILE IS

EVERYWHERE

2005

2013

WEB DEVELOPERS?

NATIVE

  • Developed in platform language (Swift, Java, C#)
  • Distributed via Apps Stores
  • Access to advanced devices features (FyleSystem, payments, contacts)
  • Push notifications
  • Native UI

NATIVE

Performance

User experience

Hardware access

Vendor platform

Updates

Development costs

WEB

  • Developed with web technologies
  • Distributed via mobile browsers
  • Access to limited devices features
  • No push notifications
  • Customizable UI

WEB

Open technologies

Updates

Development costs

Performance

User Experience

Accesibility

HYBRID

  • Developed with web technologies and native components
  • Distributed via App Stores
  • Access to several devices features
  • Customizable and native (emulated) UI

HYBRID

CrossPlatform

Web Technologies

Development costs

No UI Restrictions

Hardware access

Performance

User Experience

Updates

WHEN GO TO HYBRID

  • Which platforms to target?
  • Distribute via App Stores?
  • Need mobile capabilities?
  • Team skills

FRAMEWORKS

BOOTSTRAP PROJECT

$ ionic start ionic-example tabs

PREVIEW APP

$ ionic serve
$ ionic serve --lab

BUILD APP

$ ionic platform add android
$ ionic build android

platforms/android/ant-build/*.apk

$ ionic platform add ios
$ ionic build ios

platforms/ios/build/emulator/*.app

TEST APP

$ ionic emulate android
$ ionic run android

Local

Remote

DEVELOP

TIME!

SIDEBAR (I)

<ion-side-menus>
    <!-- Center content -->
    <ion-side-menu-content>
        <ion-nav-bar class="bar-positive">
            <ion-nav-back-button></ion-nav-back-button>
        </ion-nav-bar>
        <ion-nav-view></ion-nav-view>
    </ion-side-menu-content>
    <!-- Left menu -->
    <ion-side-menu side="left">
        <ion-list>
            <ion-item class="item-avatar" type="item-text-wrap">
                <img ng-src="{{user.avatar}}">
                <h2>{{user.name}}</h2>
                <p>{{user.city}}</p>
            </ion-item>
            <ion-item menu-close class="item-icon-right"
                type="item-text-wrap"
                href="#/login">
                
                <h2>Logout</h2>
            </ion-item>
        </ion-list>
    </ion-side-menu>
</ion-side-menus>

index.html

SIDEBAR (II)

angular.module('starter.controllers', [])
    .controller('MainCtrl', function(
        $scope,
        $ionicSideMenuDelegate,
        $ionicPopover
    ) {

        $scope.user = {
            avatar: 'http://www.gravatar.com/avatar/' +
                    '7e6af66d57801c031359233b5756e884.png',
            name: 'Anthanh Pham Trinh',
            city: 'Mordor City'
        };
    
        // ...
    
    });

controller.js:MainCrtl

<ion-nav-bar class="bar-positive">
    <ion-nav-back-button></ion-nav-back-button>
    <ion-nav-buttons side="left">
        <button menu-toggle="left"
            class="button button-icon icon ion-navicon">
        </button>
    </ion-nav-buttons>
</ion-nav-bar>

index.html

POPOVER (I)

<ion-nav-bar class="bar-positive">
    <!-- ... -->
    <ion-nav-buttons side="right">
        <button menu-toggle="right"
            class="button button-icon icon ion-android-more-vertical"
            ng-click="showActionsMenu($event)">
        </button>
    </ion-nav-buttons>
</ion-nav-bar>

index.html

<ion-popover-view> <ion-content>
        <ion-list>
            <ion-item menu-close
                class="item-icon-right"
                type="item-text-wrap"
                href="#/login"
                ng-click="hideActionsMenu()">

                <h3>Logout</h3>
            </ion-item>
        </ion-list>
</ion-content> </ion-popover-view>

popover.html

POPOVER (II)

angular.module('starter.controllers', [])
  .controller('MainCtrl', function(
        $scope,
        $ionicSideMenuDelegate,
        $ionicPopover
    ) {

    // ...

    $ionicPopover.fromTemplateUrl('templates/popover.html', {
        scope: $scope
    }).then(function(popover) {
        $scope.popover = popover;
    });

    $scope.showActionsMenu = function($event) {
        $scope.popover.show($event);
    };

    $scope.hideActionsMenu = function() {
        $scope.popover.hide();
    };

  }));

controllers.js

LOGIN (I)

<ion-view view-title="Login">
    <ion-content>
        <div class="list">
            <label class="item item-input item-floating-label">
                <span class="input-label">Email</span>
                <input type="text" placeholder="Email">
            </label>
            <label class="item item-input item-floating-label">
                <span class="input-label">Password</span>
                <input type="password" placeholder="Password">
            </label>
        </div>
        <div class="padding">
            <button
                class="button button-block button-positive"
                ng-click="login()">login</button>
        </div>
    </ion-content>
</ion-view>

templates/login.html

LOGIN (II)

.controller('LoginCtrl', function($scope, $state) {
	$scope.login = function() {
		$state.go('tab.dash');
	};
})

controllers.js:LoginCtrl

$stateProvider.state('login', {
    url: '/login',
    templateUrl: 'templates/login.html',
    controller: 'LoginCtrl'
});

app.js

ON-SCROLL REFRESH

<ion-view view-title="Chats">
    <ion-content>
        <ion-refresher
            pulling-text="Pull to refresh..."
            on-refresh="doRefresh()">
        </ion-refresher>
        <ion-list>
            <!-- ... -->
        <ion-list>
    </ion-content>
</ion-view>

tab-chats.html

.controller('ChatsCtrl', function($scope, $timeout) {
    $scope.doRefresh = function() {
        $timeout(function() { // async emulation
            $scope.$broadcast('scroll.refreshComplete');
        }, 1000);
    };
})

app.js

STYLING

$ ionic setup sass
.menu.menu-left .item-avatar {
    background-color: $royal;
    h2, p {
        color: white;
    }
}

.popover {
	height: 4em;
}

scss/ionic.app.scss

[{
 "id": "0",
 "name": "Ben Sparrow",
 "lastText": "You on your way?",
 "face": "https://pbs.twimg.com/profile_images/514549811765211136/9SgAuHeY.png"
}, ... ]

res/chats.json

$scope.doRefresh = function() {
    Chats.more().success(function(chats) {
        $scope.chats = $scope.chats.concat(chats);
        $scope.$broadcast('scroll.refreshComplete');
    }).error(function() {
        $scope.$broadcast('scroll.refreshComplete');
    });
};

controllers.js:ChatsCrtl

BACKEND RESOURCES

.factory('Chats', function($http) {
    return {
        more: function() {
            return $http.get('res/chats.json');
        },
        ...
    };
});

services.js

EXAMPLE PROJECT

https://github.com/anthanh/ionic-example

MUCH MORE!

DON'T TRY IT ALONE! GET INSPIRED

THANKS!

Anthanh Pham Trinh - @antaipt

ionic Framework

By Anthanh

ionic Framework

A starter guide to build hybrid-mobile apps with ionic Framework

  • 4,093