Ionic2 - the raise of web developer, Riviera DEV le 17/06/2016

71
The raise of web developers @loicknuchel

Transcript of Ionic2 - the raise of web developer, Riviera DEV le 17/06/2016

The raise of web developers

@loicknuchel

?

L’histoire du smartphone

Juin 2007

Lancement de l’iPhone 1

Septembre 2008

Sortie du HTC G1avec Android

● Nouvelles possibilités○ UX○ Technique○ Business

● Un écosystème à bâtir

● Nouvelle stack technique

● Peu de personnes formées

● Développer plusieurs fois la même chose

● Environnements très spécifiques (offline, puissance, versions, diversité...)

La WebView

Idée

Coder des applicationsentièrement dans la WebView

Avantages :

● Technologies et environnements connus● Cross-platform

PhoneGap / Cordova

Mars 2009 :Lancement de PhoneGap par Nitobi

Octobre 2011 :Rachat de Nitobi par AdobeSéparation de la technologie (Cordova) et des services commerciaux (PhoneGap)

Oups...● UI moche● UI peu réactive● loin du look & feel natif

Mauvais support des standards du web dans la WebView

Peu d’outils / librairies

Téléphones peu puissants

● App de mauvaise qualité● Bugs

Souvent pour des projets à petit budget...

Aujourd’hui

● Téléphones puissants (et de + en +)

● Très bon support des standards web dans la WebView

● Beaucoup d’outils / librairies

Ionic c’est quoi ?

+ =

Stack technologique

Natif

Web

Téléphone & APIs natives

Cordova : webview +JavaScript bridges

Angular

Ionic

Application

Dév web = Dév mobile

DX“We want to cater to the 99% who just want to build something functional quickly

and not break the bank to do it.” - Max Lynch

DX#Platform continuity

#CLI

#Backend services

#Push#Deploy

#Package#Auth#Analytics #Ionic View

#Native plugins #Ionic Market

#Ionic Creator

@ionitron

Ionic is a complete ecosystem !

One more thing...

Hybrid apps have superpowers...

Hybrid superpowers

App Store installs are broken !

?http://bit.ly/voxxrin

App Store installs are broken !

Deep linking Install tracking

Hybrid superpowers

Web App :

● Cross-platform● Accès instantané● Deep link● Offline

http://bit.ly/voxxrin-bdx-lkn

Hybrid superpowers

Web App :

● Cross-platform● Accès instantané● Deep link● Offline

Progressive Web App :

● Installation instantanée● Lancement depuis la Home● Push notifications

Hybrid superpowers

Web App :

● Cross-platform● Accès instantané● Deep link● Offline

Progressive Web App :

● Installation instantanée● Lancement depuis la Home● Push notifications

Native App :

● Accès complet au téléphone

Hybrid superpowers

App Store deployment is broken !

Apple : ~ 2 jours

Google : ~ 2 heures

Hybrid superpowers

Nouveautés depuis Ionic 1

● Angular 2 (+ TypeScript)● Navigation push/pop● Nouveaux composants

○ DateTime○ Toast○ Searchbar○ Segment

Getting started

Install nodejs & npm

$ npm install -g ionic@beta

$ ionic start demoApp --v2 --ts

$ cd demoApp && ionic serve

♬ ♫ ♬ ♫ Your Ionic app is ready to go! ♬ ♫ ♬ ♫

Getting started

Install mobile sdk (Android ou iOS)

$ sudo npm install -g cordova

$ ionic platform add android

$ ionic run android

Structure de fichiers

index.html<!DOCTYPE html><html lang="en" dir="ltr"><head> <meta charset="UTF-8"> <title>Ionic</title> <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"> <meta name="format-detection" content="telephone=no"> <meta name="msapplication-tap-highlight" content="no">

<link ios-href="build/css/app.ios.css" rel="stylesheet"> <link md-href="build/css/app.md.css" rel="stylesheet"> <link wp-href="build/css/app.wp.css" rel="stylesheet"></head><body> <!-- this Ionic's root component and where the app will load --> <ion-app></ion-app>

<!-- cordova.js required for cordova apps --> <script src="cordova.js"></script> <!-- Polyfill needed for platforms without Promise and Collection support --> <script src="build/js/es6-shim.min.js"></script> <!-- Zone.js and Reflect-metadata --> <script src="build/js/Reflect.js"></script> <script src="build/js/zone.js"></script> <!-- the bundle which is built from the app's source code --> <script src="build/js/app.bundle.js"></script></body></html>

app.tsimport {App, Platform} from 'ionic-angular';import {StatusBar} from 'ionic-native';import {TabsPage} from './pages/tabs/tabs';

@App({ template: '<ion-nav [root]="rootPage"></ion-nav>', config: {} // http://ionicframework.com/docs/v2/api/config/Config/})export class MyApp { rootPage: any = TabsPage;

constructor(platform: Platform) { platform.ready().then(() => { // Okay, so the platform is ready and our plugins are available. // Here you can do any higher level native things you might need. StatusBar.styleDefault(); }); }}

page1.tsimport {Page} from 'ionic-angular';

@Page({ templateUrl: 'build/pages/page1/page1.html'})export class Page1 { constructor() {

}}

<ion-navbar *navbar> <ion-title>Tab 1</ion-title></ion-navbar>

<ion-content padding class="page1"> <h2>Welcome to Ionic!</h2> <p> This starter project comes with simple tabs-based layout for apps that are going to primarily use a Tabbed UI. </p> <p> Take a look at the <code>app/</code> directory to add or change tabs, update any existing page or create new pages. </p></ion-content>

page1.tsimport {Page} from 'ionic-angular';

@Page({ template: `<ion-navbar *navbar> <ion-title>Tab 1</ion-title></ion-navbar>

<ion-content padding class="page1"> <h2>Welcome to Ionic!</h2> <p> This starter project comes with simple tabs-based layout for apps that are going to primarily use a Tabbed UI. </p></ion-content>`})export class Page1 { constructor() {}}

page1.tsimport {Page} from 'ionic-angular';

@Page({ styles: [`.page1 h2 { color: red;} `], template: `...`})export class Page1 { constructor() {}}

Angular 1 vs Angular 2

● bootstrap manuel

● Filter => Pipe

● Controllers => Components

● Directives => Components

● $scope => Class properties

● Services => Injectables

Template

● Bindings :

● Pipes :

● Propriétés / Input :

● Evénements / Output :

● Double binding :

● Templates :

● Local variables :

● Boucles :

Your favorite hero is: {{favoriteHero}}

<span>{{movie.title | uppercase}}</span>

<a [href]="angularDocsUrl">Angular Docs</a>

<button (click)="toggleMovie()"></button>

<input [(ngModel)]="favoriteMovie" />

<div *ngIf="movies.length === 0">No movies</div>

<video-player #player></video-player><button (click)="player.pause()">Pause</button>

<ul *ngFor="let movie of movies"> <li>{{movie.title}}</li></ul>

Créer une nouvelle page

todo.page.ts todo.html todo.scssimport {Page} from 'ionic-angular';

@Page({ templateUrl: 'build/pages/todo/todo.html'})export class TodoPage { constructor() { }}

<ion-navbar *navbar> <ion-title>Todos</ion-title></ion-navbar>

<ion-content class="todo-page">

</ion-content>

.todo-page { .done { text-decoration: line-through; }}

import {App, Platform} from 'ionic-angular';import {StatusBar} from 'ionic-native';import {TabsPage} from './pages/tabs/tabs';import {TodoPage} from "./pages/todo/todo.page";

@App({ template: '<ion-nav [root]="rootPage"></ion-nav>', config: {}})export class MyApp { rootPage: any = TodoPage;

constructor(platform: Platform) { platform.ready().then(() => { StatusBar.styleDefault(); }); }}

// http://ionicframework.com/docs/v2/theming/

// App Shared Imports// --------------------------------------------------// These are the imports which make up the design of this app.// By default each design mode includes these shared imports.// App Shared Sass variables belong in app.variables.scss.

@import "../pages/page1/page1";@import "../pages/page2/page2";@import "../pages/page3/page3";@import "../pages/todo/todo";

app.ts theme/app.core.scss

Ionic2 TODO listimport {Page} from 'ionic-angular';

class Todo { constructor( public name: string, public done: boolean = false ) {}}

@Page({ templateUrl: 'build/pages/todo/todo.html'})export class TodoPage { constructor() { }}

<ion-navbar *navbar> <ion-title>Todos</ion-title></ion-navbar>

<ion-content class="todo-page">

</ion-content>

Ionic2 TODO listimport {Page} from 'ionic-angular';

class Todo { constructor( public name: string, public done: boolean = false ) {}}

@Page({ templateUrl: 'build/pages/todo/todo.html'})export class TodoPage { todos: Todo[] = [ new Todo('todo 1'), new Todo('todo 2'), new Todo('todo 3') ];

constructor() { }}

<ion-navbar *navbar> <ion-title>Todos</ion-title></ion-navbar>

<ion-content class="todo-page">

</ion-content>

Ionic2 TODO list<ion-navbar *navbar> <ion-title>Todos</ion-title></ion-navbar>

<ion-content class="todo-page"> <ion-list> <ion-item *ngFor="let todo of todos" [hidden]="todo.done"> <ion-label>{{todo.name}}</ion-label> <ion-checkbox [(ngModel)]="todo.done"></ion-checkbox> </ion-item> <ion-item *ngFor="let todo of todos" [hidden]="!todo.done"> <ion-label class="done">{{todo.name}}</ion-label> <ion-checkbox [(ngModel)]="todo.done" disabled="true"></ion-checkbox> </ion-item> </ion-list></ion-content>

Ionic2 TODO listimport {Page} from 'ionic-angular';

@Page({ templateUrl: 'build/pages/todo/todo.html'})export class TodoPage { newTodo: string = ''; todos: Todo[] = [ new Todo('todo 1'), new Todo('todo 2'), new Todo('todo 3') ];

constructor() { }

create(text: string): void { this.todos.push(new Todo(text)); this.newTodo = ''; }}

<ion-navbar *navbar> <ion-title>Todos</ion-title></ion-navbar>

<ion-toolbar> <ion-input type="text" [(ngModel)]="newTodo" placeholder="Nouvelle tâche"> </ion-input> <ion-buttons end> <button (click)="create(newTodo)"> <ion-icon name="send"></ion-icon> </button> </ion-buttons></ion-toolbar>

<ion-content class="todo-page"> <ion-list> ... </ion-list></ion-content>

Ionic2 TODO listimport {Page} from 'ionic-angular';

@Page({ templateUrl: 'build/pages/todo/todo.html'})export class TodoPage { newTodo: string = ''; todos: Todo[] = [...];

constructor() { }

create(text: string): void { ... }

delete(todo: Todo): void { const i = this.todos.indexOf(todo); if(i >= 0) { this.todos.splice(i, 1); } }}

<ion-navbar *navbar> <ion-title>Todos</ion-title></ion-navbar>

<ion-toolbar> ...</ion-toolbar>

<ion-content class="todo-page"> <ion-list> <ion-item *ngFor="let todo of todos" [hidden]="todo.done"> <ion-label>{{todo.name}}</ion-label> <ion-checkbox [(ngModel)]="todo.done"></ion-checkbox> </ion-item> <ion-item *ngFor="..." [hidden]="!todo.done" (click)="delete(todo)"> <ion-label class="done">{{todo.name}}</ion-label> <ion-checkbox [(ngModel)]="todo.done" disabled="true"></ion-checkbox> </ion-item> </ion-list></ion-content>

Ionic2 TODO listimport {Page} from 'ionic-angular';

@Page({ templateUrl: 'build/pages/todo/todo.html'})export class TodoPage { newTodo: string = ''; todos: Todo[] = [...];

constructor() { }

create(text: string): void { ... }

delete(todo: Todo): void { const i = this.todos.indexOf(todo); if(i >= 0) { this.todos.splice(i, 1); } }}

<ion-navbar *navbar> <ion-title>Todos</ion-title></ion-navbar>

<ion-toolbar> ...</ion-toolbar>

<ion-content class="todo-page"> <ion-list> <ion-item *ngFor="let todo of todos" [hidden]="todo.done"> <ion-label>{{todo.name}}</ion-label> <ion-checkbox [(ngModel)]="todo.done"></ion-checkbox> </ion-item> <ion-item *ngFor="..." [hidden]="!todo.done" (click)="delete(todo)"> <ion-label class="done">{{todo.name}}</ion-label> <ion-checkbox [(ngModel)]="todo.done" disabled="true"></ion-checkbox> </ion-item> </ion-list></ion-content>

Pour tester ce weekend...

Questions ?

@loicknuchel