logo

Building Hybrid Apps with Ionic 2

@nicobytes
tutor
               
{
  name: 'Nicolas Molina Monroy',
  twitter: '@nicobytes',
  website: 'https://nicobytes.com',
  github: 'https://github.com/nicobytes'
  jobs: [
      'Hybrid App Developer',
      'Front-End Developer'    
  ],
  organizer: [
      'http://www.meetup.com/es/Hybrid-Apps-Colombia',
      'http://www.meetup.com/es/Django-Bogota'  
  ]
}
              
            
book
www.ion-book.com
blog

Colombia

Peru

Bolivia

Review

Web Technologies You Already

Know & Love

(You'll feel right at home)

IBM Mobile

http://www.ibm.com/mobilefirst/ showcase

Apps

showcase showcase showcase showcase

Ionic V1 is great

But a lot's changed since its release

2 years is a long time in web tech!

A lot's changed

Better/faster devices!

Fewer slow/bad devices!

Widely available web APIs!

Improved browser engines!

V2 Goals

  1. Simplicity
  2. Native UX
  3. Navigation
  4. Creative Freedom
  5. Future Proof

Talk is cheap

Let's see some code

1. Simplicity

Using properties instead of classes.

2. Native UX

The different modes for Ionic 2.

3. Navigation

More robust and powerful.

5. Creative Freedom

Make anything possible.

6. Future Proof

Building Ionic with new standards.

JavaScript has changed

Ionic 1 was built with ES5

ES6 brings many new features

NG2 is pushing for ES6

Different look, but all JS Classes

TypeScript

ES6 + ES7 Decorators + Types

Ionic 2 and NG2 built using TS

Code completion in your editor

Ionic 2

The course

level
Class 1
Concepts
level
Class 2
Understanding Ionic 2
level
Class 3
Artifacts in Ionic 2
level
Class 4
Navigation
level
Class 5
UI/UX
level
Class 6
Ionic SDK
level
Class 7
Forms & Validations
level
Class 8
Data I
level
Class 9
Data II
level
Class 10
Native
level
Class 11
Build & Deploy
level
Class 12
Demo Day
level

Class 1: Concepts

Basics

  1. ¿What is HybridApp?
  2. Showcases
  3. New Concepts (ES6, Typescript, Angular)
  4. Transpiling
  5. Web Components.

¿What is HybridApp?

“I want to build an app!”

More Platforms. More Problems.

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

Why are we still coding for multiple platforms?

“Is there an alternative?”

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!)

hybrid-app
“Oh No! The Zuck has spoken!”

http://techcrunch.com/2012/09/11/mark-zuckerberg-our-biggest-mistake-with-mobile-was-betting-too-much-on-html5/

“Hybrid apps are slow!”
“The Times They Are a-Changin'”

STATE

“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

Showcases

level
http://showcase.ionicframework.com/
http://blog.ionic.io/tag/built-with/

New Concepts

ECMAScript 6 (ES6)

Classes (Antes)

               
var Person = function (name, age) {
    this.name = name;
    this.age = age;
};
Person.prototype.getName = function () {
    return this.name;
};
              
            

Classes (Ahora)

               
class Person {
  name;
  age;

  constructor (name, age) {
    this.name = name;
    this.age = age;
  }

  getName(){
    return this.name;
  }
}
              
            

Modules (Antes)

               
//  lib/math.js
LibMath = {};
LibMath.multiply = function (x, y) { return x * y };

//  someApp.js
var math = LibMath;
console.log(math.multiply(2, 2));
              
            

Modules (Ahora)

               
export function multiply (x, y) { return x * y }
export var url = 'http://api.domain.com';

import { multiply, url } from "./math"
console.log(multiply(2, 2))
              
            

Promises (Antes)

               
function doSomething (onDone) {
  onDone();
}

doSomething(function(rta){
  console.log(rta);
})
              
            

Promises (Ahora)

               
doLogin().then((rta) => {
  console.log(rta);
});
              
            
level
level

Promises

               
doLogin()
.then((rta) => {
  console.log(rta);
})
.then((rta) => {
  console.log(rta);
})
.then((rta) => {
  console.log(rta);
})
.catch((error) => {
  console.log(error);
})
              
            

Block Scoping (Antes)

               
(function() {
    'use strict';

    //Code
})();
              
            

Block Scoping (Ahora)

               
for (let i = 0; i < a.length; i++) {
  let x = a[i];
}
              
            

let y const (Antes)

               
if(true) {
  var twitter = "@nicobytes";
}
console.log(twitter); //twitter es global
//Const no existe en ES5
              
            

let y const (Ahora)

               
const PI = 3.14;
if(true) {
  let twitter = "@nicobytes";
}
console.log(twitter); //Error porque twitter ha sido definida dentro de IF
console.log(PI); //3.14

PI = 3.12; //Error porque PI es un constante y no puede cambiar de valor una vez definida.

              
            

Fat Arrow Functions (Antes)

               
var numbers = [1,2,3,4];
numbers.map(function(item){
  return item * 2;
}); //[2,4,6,8]

function Person(){
  this.foo = function(){}
  this.bar = function(){
    var self = this;
    document.addEventListener("click", function(e){
      self.foo();
    });
  }
}
              
            

Fat Arrow Functions (Ahora)

               
let numbers = [1,2,3,4];
numbers.map(item => item * 2); //[2,4,6,8]

class Person(){
  foo(){}
  bar(){
    document.addEventListener("click", (e) => this.foo());
  } 
}
              
            
http://es6-features.org/
ES6 & Ionic 2

Typescript

Transpiling

Web Components

Decorators

Import & Export

Dependency Injection

level

Class 2: Understanding Ionic 2

Installing Ionic

Install: https://ionicframework.com/docs/v2/setup/installation/

Build

SO Android IOS
Window
Mac
Linux / Ubuntu

For Android: http://cordova.apache.org/docs/en/latest/guide/platforms/android/index.html

For IOS: http://cordova.apache.org/docs/en/latest/guide/platforms/ios/index.html

Generate your first app

               
ionic start appBlank blank --v2
ionic start appSide sidemenu --v2
ionic start appTabs tabs --v2
cd yourApp
ionic serve
              
            
               
ionic start
              
            

TypeScript

TypeScript = Transpiling

  • ES6
  • Export & Import
  • Clases
  • Types
  • Modifiers
  • Functions

Introducción a TypeScript: https://www.ion-book.com/blog/ionic2/intro-typescript/

Syntax Angular 2

Data Binding

               
<input [value]="twitter">
<button (click)="doChange()">
<p> Hola {{twitter}} </p>
<input [value]="twitter" (input)="twitter = $event.target.value">
<input [(ngModel)]="twitter">
               
            

Local Variable

               
<p #myVar></p>
<button (click)="myVar.innerHTML = 'test.'">
               
            

Directives

  • *ngIf
  • *ngFor

Anatomy

  • src
  • www
  • plugins
  • platforms
  • resources
  • hooks

Ionic Cli

Basic Usage

               
ionic start myAwesomeApp --v2 --ts
cd myAwesomeApp
ionic info
ionic serve
              
            

Platform

               
ionic platform add android --save
ionic platform add ios --save
ionic platform add wp --save
ionic platform ls
ionic platform rm android
              
            

Run

               
ionic run android
ionic run ios
              
            

Build

               
ionic build android
ionic build ios
ionic build android --release
ionic build ios --release
              
            

Emulate

               
ionic emulate android
ionic emulate ios
              
            

State

               
ionic state save
ionic state restore
              
            

Plugins (Native)

               
ionic plugin add cordova-plugin-XXXXXX save
//Examples
ionic plugin add cordova-plugin-camera --save
ionic plugin add cordova-plugin-googlemaps --save
ionic plugin add phonegap-plugin-push --save
ionic plugin rm phonegap-plugin-push --save
ionic plugin ls
              
            

Libs (npm)

               
npm install moment --save
              
            

Resources

               
ionic resources
              
            
level

Class 3: Artifacts in Ionic 2

Decorators

  1. Decorators (@Component, @Directive, @Pipe and @Injectable)
  2. Ionic Generator
  3. Pages
  4. Components
  5. Directives
  6. Pipes
  7. Injectables
               
@Decorator({
  //meta data
})
export class MyClass {
  //Your class
}
              
            
  • @Component
  • @Injectable
  • @Pipe
  • @Directive

Generator

               
ionic g --list
              
            

Page

               
ionic g page users
              
            

It is a component

               
import { Component } from '@angular/core';
import { NavController } from 'ionic-angular';

@Component({
  selector: 'users-page',
  templateUrl: 'users.html',
})
export class UsersPage {

  constructor(private nav: NavController) {

  }

}
              
            

User Component

               
ionic g component my-user
              
            

User Component

               
import { Component, Input } from '@angular/core';

@Component({
  selector: 'my-user',
  templateUrl: 'my-user.html'
})
export class MyUser {

  text: string;
  @Input() hero: any;

  constructor() {
    this.text = 'Hello World';
  }
}
              
            

Include in NgModule

Template

               
<my-user *ngFor="let user of users" [hero]="user"></my-user>
              
            

Directives

              
ionic g directive my-highlight
              
            
              
import { Directive, ElementRef } from '@angular/core';
@Directive({
  selector: '[my-highlight]' // Attribute selector
})
export class MyHighlight {
  constructor(el: ElementRef) {
    el.nativeElement.style.backgroundColor = 'yellow';
  }
}
              
            

Template

              
<h1 my-highlight>Hola</h1>
              
            

Include in NgModule

Pipe

              
ionic g pipe reverse
              
            
              
import { Injectable, Pipe } from '@angular/core';
@Pipe({
  name: 'reverse'
})
@Injectable()
export class Reverse {
  transform(value: string, args: any[]) {
    return value.split('').reverse().join('');
  }
}
              
            

Include in NgModule

Template

              
<h1>{{ 'Hola' | reserve }}</h1>
              
            

Provider

              
ionic g provider usersService
              
            
              
import { Injectable } from '@angular/core';
import { Http } from '@angular/http';
import 'rxjs/add/operator/map';
@Injectable()
export class usersService {
  data: any;

  constructor(private http: Http) {
    this.data = null;
  }

  load() {
    //Code
  }
}
              
            

Include in NgModule

Inject

              
export class UsersPage {

  users: any[];

  constructor(
    private nav: NavController,
    private usersService: UsersService
  ) {
    this.usersService.load();
    this.users = [
      {
        name: 'as'
      },
      {
        name: 'as'
      }
    ];
  }

}
              
            
Ionic Generator
level

Class 4: Navigation

Navigation

  1. Push, Pop y setRoot.
  2. Url parameters.
  3. Tabs, Menus, Modal, Alerts.

Push

              
// 1.
import { NavController } from 'ionic-angular';
// 2.
constructor(
    private nav: NavController,
    private heroesService: HeroesService
  ) {
// 3.
this.nav.push( HeroPage );
              
            

Pop

              
// 1.
import { NavController } from 'ionic-angular';
// 2.
constructor(
    private nav: NavController,
    private heroesService: HeroesService
  ) {
// 3.
this.nav.pop();
              
            

setRoot

              
this.nav.setRoot( page );
              
            

Passing Data

              
this.nav.push(somethingPage, {
  example1: data1,
  example2: data2
});
              
            

Passing Data

              
import {Component} from '@angular/core';
import {NavController, NavParams} from 'ionic-angular';
@Component({
templateUrl: 'build/pages/second/second.html'
})
export class somethingPage {
  constructor(nav: NavController, navParams: NavParams){
    this.navParams.get('example1');
  }
}
              
            

Modals

Docs

Tabs

Docs

Menus

Menu
              
<ion-menu [content]="content">
  <ion-content>
    <ion-list>
      <button menuClose ion-item (click)="openTabsPage()">Tabs</button>
      <button menuClose ion-item (click)="openHeroesPage()">Heroes</button>
       <button menuClose ion-item (click)="close()" >Cerrar </button >
    </ion-list>
  </ion-content>
</ion-menu>

<ion-nav id="nav" #content [root]="rootPage"></ion-nav>
              
            
              
export class MenuPage {
  private rootPage: any;

  constructor(private nav: NavController) {
    this.rootPage = TabsPage;
  }

  openHeroesPage(){
    this.rootPage = HeroesPage;
  }

  close(){
    this.nav.setRoot( LoginPage );
  }

}
              
            
              
<button menuToggle>
  <ion-icon name="menu"></ion-icon>
</button>
              
            
level

Class 5: UI/UX

UI/UX

  1. Ionic & Sass.
  2. Material Desing.
  3. IOS Stlye.
  4. Window Phone Desing.
  5. UI Components.

Sass

Documentation

Files

  • src/app/app.scss
  • src/app/variables.scss

Variables

src/theme/variables.scss
              
$colors: (
  primary:    #387ef5,
  secondary:  #32db64,
  danger:     #f53d3d,
  light:      #f4f4f4,
  dark:       #222,
  favorite:   #69BB7B
);
              
            

Custom Colors

              
$colors: (
  // ...
  twitter:    #55acee
)
              
            

Apply

              
<button twitter>Twitter</button>
              
            

Custom Colors

              
$colors: (
  // ...
  twitter:(
    base: #55acee,
    contrast: #ffffff
  )
)
              
            

In scss

              
.home {
 p{
     background: color($colors, twitter, base);
 } 
}
              
            

Sass Variables

              
$my-padding: 10px;
              
            

Apply

              
.home {
 p{
     background: color($colors, twitter, base);
     padding: $my-padding;
 } 
}
              
            

Utility Attributes

Utilities

Platform Specific Styles

Docs

Apply

              
.md button {
  background: red;
}
.ios button {
  background: blue;
}
.wp button {
  background: green;
}
              
            

In html

              
<button [class.myclass]="true">Twitter</button>
<button [attr.no-lines]="true">Twitter</button>
              
            

Overriding Ionic Sass Variables

Docs
              
// App iOS Variables
// --------------------------------------------------
// iOS only Sass variables can go here
$button-ios-border-radius: 20px;
              
            

Overwrite

              
button[primary]{
  background: black;
 }
              
            

Icons

Icons v1

Icons v2

Custom icons

Inlcude

              
<link href="build/font-awesome/css/font-awesome.min.css" rel="stylesheet" >
              
            

Icomoon

level

Class 6: Ionic SDK

UI Components (without JS)

Badges

Buttons

Cards

Checkbox

Datetime

Gestures

Grid

List

Slides

UI Components (with JS)

Alerts

Action Sheet

Loading

Resumen

level

UX/UI

Sass un Prepocesador

En el vas a poder tener orden de tu CSS, automatizar trabajo, escalabilidad del proyecto y ahorro de tiempo.

Usado en:

  1. compass
  2. bourbon
  3. bootstrap
  4. Foundation

Sintaxis:

Se puede utilizar dos tipos de sintaxis *.sass y *.scss

                
*.scss

body {
  font: 100% $font-stack;
  color: $primary-color;
}

*.sass
body
  font: 100% $font-stack
  color: $primary-color
              
            

Variables:

                
$font-stack:    Helvetica, sans-serif;
$primary-color: #333;

body {
  font: 100% $font-stack;
  color: $primary-color;
}
              
            

Nesting:

                
nav {
  ul {
    margin: 0;
    padding: 0;
    list-style: none;
  }

  li { display: inline-block; }

  a {
    display: block;
    padding: 6px 12px;
    text-decoration: none;
  }
}
              
            

Partials:

Nos van a servir para declarar todos los archivos que pueden ser importados ejemplo.scss

Mixins

                
@import 'reset';

body {
  font: 100% Helvetica, sans-serif;
  background-color: #efefef;
}
              
            

Import

                
@mixin border-radius($radius) {
  -webkit-border-radius: $radius;
     -moz-border-radius: $radius;
      -ms-border-radius: $radius;
          border-radius: $radius;
}

.box { @include border-radius(10px); }
              
            

Extend

                
.message {
  border: 1px solid #ccc;
  padding: 10px;
  color: #333;
}

.success {
  @extend .message;
  border-color: green;
}
              
            

Mayor control y calidad de codigo

Material Desing, IOS Stlye y Window Phone Style.

Theming in Ionic.

Variables de Ionic.

Estilos propios.

Utilidades.

Componente: Ion-icon

Agregar iconos propios (Font Awesome)

Resumen

level

Class 7: Forms & Validations

Forms

  1. Binding with ngModel.
  2. FormBuilder.
  3. Validations.
  4. Custom validations.

ngModel

              
<form (ngSubmit)="saveData()">
  <ion-input type="text" required name="username" [(ngModel)]="model.username"></ion-input>
  <ion-input type="text" required name="name" [(ngModel)]="model.name"></ion-input>
  <button primary block type="submit">Save</button>
</form>
              
            

Control

              
this.username = new Control(
  'Default value',
  Validators.required
  /*Async*/
);
              
            

Control

              
<input type="text" 
ngControl="username" 
[(ngModel)]="model.username" 
name="username" />
              
            

FormBuilder & ControlGroup

              
myForm: ControlGroup;
//
constructor(
    private formBuilder: FormBuilder
  ) {
              
            

Form

              
this.username = new Control('', Validators.required);
this.name = new Control('', Validators.required);
this.myForm = this.formBuilder.group({
  username: this.username,
  name: this.name,
})
              
            

Form

              
<form (ngSubmit)="saveData()" [formGroup]="myForm" novalidate>
  <ion-input type="text" 
  name="username" 
  formControlName="username"></ion-input>
  <ion-input type="text" 
  name="name" 
  formControlName="name"></ion-input>
  <button primary block type="submit">Save</button>
</form>
              
            

Show errors

              
<div *ngIf="username.dirty && !username.valid">
    <p *ngIf="username.errors.required">
      Este campo es requerido
    </p>
</div>
              
            

Validations

  • Validators.required
  • Validators.minLength(4)
  • Validators.maxLength(8)
  • Validators.pattern('[a-zA-Z ]*')

Validations compose

              
Validators.compose([
  Validators.required,
  Validators.minLength(4),
  Validators.maxLength(8),
  Validators.pattern('[a-zA-Z ]*')
])
              
            

Control

              
this.username = new Control(
  '',
  Validators.compose([
    Validators.required,
    Validators.minLength(4),
    Validators.maxLength(8),
    Validators.pattern('[a-zA-Z ]*')
  ])
);
              
            

Form

              
this.myForm = this.formBuilder.group({
  username: ['', Validators.compose([....])],
  name: ['', Validators.compose([....])],
})
              
            

Show errors

              
<div *ngIf="myForm.controls.username.dirty && !myForm.controls.username.valid">
    <p *ngIf="myForm.controls.username.errors.required">
      Este campo es requerido
    </p>
</div>
              
            

saveDate

              
<button primary block type="submit" [disabled]="!myForm.valid" >Save</button>
//Or
(ngSubmit)="myForm.valid && saveData()"
              
            

Customs Validations

              
import {Control} from '@angular/common';

export class AgeValidator{
  static isOld(control: Control){
    let value = control.value;
    if(value > 18){
      return {
        'isOld': true
      }
    }
    return null;
  }
}
              
            

Include

              
import { AgeValidator } from '../../validators/age';
//Control
age: ['', AgeValidator.isReal]
              
            

Include

              
import { AgeValidator } from '../../validators/age';
//Control
age: ['', AgeValidator.isReal]
              
            
level

Class 8: Data I

Data

  1. REST API.
  2. LocaStorage.

REST API

rest

GET

https://randomuser.me/

              
return new Promise(resolve => { 
  this.http.get('https://randomuser.me/api/?results=25')
  .map(res => res.json())
  .subscribe(data => { 
    this.data = data.results;
    resolve(this.data);
  });
}); 
              
            

JSONPlaceholder

https://jsonplaceholder.typicode.com/
  • /todos (GET)
  • /todos (POST)
  • /todos/1 (GET)
  • /todos/1 (PUT)
  • /todos/1 (DELETE)

getAllTodos

              
getAllTodos() {
  return new Promise((resolve, reject) => { 
    this.http.get(`${this.path}/todos?_expand=user`)
      .map(res => res.json())
      .subscribe(data => {
        resolve(data);
      }, error =>{
        reject(error);
      })
  });
}
              
            

getTodo

              
getTodo(id: number){
  return new Promise((resolve, reject) => { 
    this.http.get(`${this.path}/todos/${id}`)
      .map(res => res.json())
      .subscribe(data => {
        resolve(data);
      }, error =>{
        reject(error);
      })
  });
}
              
            

createTodo

              
createTodo(data: any){
  return new Promise((resolve, reject) => { 
    this.http.post(`${this.path}/todos`, data)
      .map(res => res.json())
      .subscribe(data => {
        resolve(data);
      }, error =>{
        reject(error);
      })
  });
}
              
            

editTodo

              
editTodo(data: any){
  return new Promise((resolve, reject) => { 
    this.http.post(`${this.path}/todos`, data)
      .map(res => res.json())
      .subscribe(data => {
        resolve(data);
      }, error =>{
        reject(error);
      })
  });
}
              
            

deleteTodo

              
deleteTodo(data: any){
  return new Promise((resolve, reject) => { 
    this.http.post(`${this.path}/todos`, data)
      .map(res => res.json())
      .subscribe(data => {
        resolve(data);
      }, error =>{
        reject(error);
      })
  });
}
              
            

Headers

              
var headers = new Headers();
headers.append('Authorization', 'Basic ----------');
this.http.post('http://api.domain.com/users', data, {
  headers: headers
})
              
            

Proxies

                
  "proxies": [
    {
      "path": "/v1",
      "proxyUrl": "https://api.instagram.com/v1"
    }
  ]
                
              

LocalStorage

              
import { Storage } from '@ionic/storage';

@NgModule({
  declarations: [
    // ...
  ],
  imports: [
    IonicModule.forRoot(MyApp)
  ],
  bootstrap: [IonicApp],
  entryComponents: [
    // ...
  ],
  providers: [
    Storage
  ]
})
export class AppModule {}
              
            
              
import { Storage, LocalStorage } from 'ionic-angular';
@Injectable()
export class TodosService {

  constructor(public storage: Storage) {}

  saveTodos( todos ){
    this.storage.set('todos', JSON.stringify(todos));
  }

  getAllTodos() {
    return this.storage.get('todos');
  }
}
              
            

Limit

5MB
level

Class 9: Data II

Data

  1. SQLite.
  2. Firebase.

SQLite

WEB SQLite / SQLite Native

              
cordova plugin add cordova-sqlite-storage --save
              
            
              
import { Injectable } from '@angular/core';
import { SQLite } from 'ionic-native';

@Injectable()
export class TasksService {

  db: SQLite = null;

  constructor() {
    this.db = new SQLite();
  }

}
              
            
              
openDatabase(){
  return this.db.openDatabase({
    name: 'data.db',
    location: 'default' // the location field is required
  });
}
              
            
              
createTable(){
  let sql = 'CREATE TABLE IF NOT EXISTS tasks(id INTEGER PRIMARY KEY AUTOINCREMENT, title TEXT, completed INTEGER)';
  return this.db.executeSql(sql, []);
}
              
            
              
getAll(){
  let sql = 'SELECT * FROM tasks';
  return this.db.executeSql(sql, [])
  .then(response => {
    let tasks = [];
    for (let index = 0; index < response.rows.length; index++) {
      tasks.push( response.rows.item(index) );
    }
    return Promise.resolve( tasks );
  })
}
              
            
              
update(task: any){
  let sql = 'UPDATE tasks SET title=?, completed=? WHERE id=?';
  return this.db.executeSql(sql, [task.title, task.completed, task.id]);
}
              
            
              
delete(task: any){
  let sql = 'DELETE FROM tasks WHERE id=?';
  return this.db.executeSql(sql, [task.id]);
}
              
            

limits

https://www.sqlite.org/limits.html

Firebase

Create Project

Install

angularfire2

               
npm install angularfire2 --save
npm install firebase --save
              
            

Config App

               
export const firebaseConfig = {
  apiKey: "xxxxxxxxxxxxxxxxxxxx",
  authDomain: "xxxxxxxxxxxxxxxxxx",
  databaseURL: "xxxxxxxxxxxxxxxxxxxxxx",
  storageBucket: "xxxxxxxxxxxxxxxxxxxxxxx",
  messagingSenderId: "xxxxxxxxxxxxxxxxxxxxx"
};
              
            

Incluir keys en NgModule

               
@NgModule({
  declarations: [
    MyApp
  ],
  imports: [
    IonicModule.forRoot(MyApp),
    AngularFireModule.initializeApp(firebaseConfig)
  ],
  bootstrap: [IonicApp],
  entryComponents: [
    MyApp
  ],
  providers: [
    AuthService
  ]
})
export class AppModule {}
              
            

Rules

               
{
  "rules": {
    ".read": true,
    ".write": true
  }
}
              
            

Service

               
import { Injectable } from '@angular/core';
import { FirebaseListObservable, AngularFire } from 'angularfire2';

@Injectable()
export class TodosService {
  
  todos: FirebaseListObservable<any>

  constructor(
    private af: AngularFire
  ) {
    this.todos = this.af.database.list('/todos');
  }
              
            

GetAllTasks

               
getAllTasks(){
  return this.todos;
}
              
            

GetAllTodos

               
getAllTodos(){
  return this.todos;
}
              
            

createTodo

               
createTodo(todo: any){
  return this.todos.push( todo );
}
              
            

updateTodo

               
updateTodo(task: any){
  return this.todos.update( task.$key, {
    title: task.title,
    completed: task.completed
  });
}
              
            

updateTodo

               
updateTodo(task: any){
  return this.todos.update( task.$key, {
    title: task.title,
    completed: task.completed
  });
}
              
            

removeTodo

               
removeTodo(task: any){
  return this.todos.remove( task.$key );
}
              
            
level

Class 10: Native

Native

  1. Cordova / Phonegap.
  2. Emulations.
  3. Ionic Native.
  4. Plugins (Camera, Geolocation, Vibration etc).

Cordova / Phonegap

Genymotion == Android

Xcode == IOS

VS == WP

GenyMotion

Check your sdk
               
android
              
            

ngCordova

Ionic native

Plugins

Install

               
ionic plugin add xxxx-xxx--xxxx --save
              
            

Adb (Android)

               
adb devices
adb start-server
adb kill-server
              
            

Run

               
ionic run android
ionic run ios
              
            
level

Class 11: Build & Deploy

Build

  1. Preparate.
  2. Signing
  3. Ionic Platform.
  4. Phonegap Build y ionic Package.
  5. PlayStore y AppStore.

Enable Production Mode

               
ionicBootstrap(MyApp, [ Providers ], {
 prodMode: true
});
              
            

Generate Icons and Splash Screens

               
ionic resources
              
            

Set the Bundle ID and App Name

               
<?xml version='1.0' encoding='utf-8'?>
<widget id="io.ionic.starter" version="0.0.1" xmlns="http://www.w3.org/ns/
widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
 <name>V2 Test</name>
 <description>An Ionic Framework and Cordova project.</description>
 <author email="hi@ionicframework" href="http://ionicframework.com/">Ionic
Framework Team</author>
              
            

Global Preferences

Minify Assets

https://tinyjpg.com/

Signing Android Applications

Generate key

               
keytool -genkey -v -keystore my-release-key.keystore -alias upload -keyalg RSA -keysize 2048 -validity 10000
              
            

Release

               
Ionic build android --release
              
            

To sign the unsigned APK

               
jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore my-release-key.keystore platforms/android/build/outputs/apk/android-release-unsigned.apk upload
              
            

Run the zip align tool to optimize the APK.

               
zipalign -v 4 platforms/android/build/outputs/apk/android-release-unsigned.apk upload.apk
              
            

Google Play

Signing iOS Applications

Apple Developer Account Required

Generate .p12

::before Generate .certSigningRequest

::before Generate mykey.key

Signing iOS Applications with MAC

Tutorial
Keychain Access > Certificate Assistant > Request a Certificate From a Certificate Authority
img

Signing iOS Applications without Mac

openssl

Signing iOS Applications without Mac

               
openssl genrsa -out mykey.key 2048
openssl req -new -key mykey.key -out myCSR.certSigningRequest -subj "/emailAddress=you@yourdomain.com, CN=Your Name, C=AU"
              
            

Done! .certSigningRequest

Upload => .certSigningRequest
Download <= .cer

developer

Generate .p12 with MAC

               
Open Keychain Access
Open .cer >  Export .p12
              
            

Generate .p12 without MAC

               
openssl x509 -in ios_development.cer -inform DER -out app_pem_file.pem -outform PEM
openssl pkcs12 -export -inkey mykey.key -in app_pem_file.pem -out app_p12.p12
              
            

Submitting an app using XCode

              
ionic build ios
              
            

Open .xcodeproj

platforms/ios/snapaday.xcodeproj
xcodeproj

Open .xcarchive

xcarchive

Validate

validate

Upload

validate

Submitting an app without Mac

Ionic Package

Phonegap Build

Application Loader

itunesconnect

Ionic Platform

platform

Push

Users

Deploy

Package

level

Class 12: Demo Day

News

http://www.ion-book.com/
http://blog.ionic.io/

Thanks