Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016

106
The rise of web developers le 21/10/2016, ionic 2.0-rc1 @loicknuchel

Transcript of Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016

Page 1: Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016

The rise of web developers

le 21/10/2016, ionic 2.0-rc1 @loicknuchel

Page 3: Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016

L’histoire du smartphone

Page 4: Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016

Juin 2007

Lancement de l’iPhone 1

Page 5: Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016

Septembre 2008

Sortie du HTC G1avec Android

Page 6: Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016

● Nouvelles possibilités○ UX○ Technique○ Business

● Un écosystème à bâtir

Page 7: Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016

● 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é...)

Page 8: Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016
Page 9: Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016

La WebView

Page 10: Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016

Idée

Coder des applicationsentièrement dans la WebView

Page 11: Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016

Idée

Coder des applicationsentièrement dans la WebView

Avantages :

● Cross-platform● Technologies et environnements connus

Page 12: Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016

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)

Page 13: Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016
Page 14: Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016

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...

Page 15: Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016

Aujourd’hui

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

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

● Beaucoup d’outils / librairies

Page 16: Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016
Page 17: Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016
Page 18: Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016
Page 19: Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016

Native develoment is ...

Page 20: Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016

way ...

Page 21: Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016
Page 22: Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016

Performance

Page 23: Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016

Code re-write

Page 24: Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016

Complicated

Page 25: Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016

Android Menu (Nav Drawer)

Source: https://developer.android.com/training/implementing-navigation/nav-drawer.html

Page 26: Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016

... @Override public boolean onCreateOptionsMenu(Menu menu) { MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.main, menu); return super.onCreateOptionsMenu(menu); } @Override public boolean onOptionsItemSelected(MenuItem item) { if (mDrawerToggle.onOptionsItemSelected(item)) { return true; } switch(item.getItemId()) { case R.id.action_websearch: Intent intent = new Intent(Intent.ACTION_WEB_SEARCH); intent.putExtra(SearchManager.QUERY, getActionBar().getTitle()); if (intent.resolveActivity(getPackageManager()) != null) { startActivity(intent); } else { Toast.makeText(this, R.string.app_not_available, Toast.LENGTH_LONG).show(); } return true; default: return super.onOptionsItemSelected(item); } } private class DrawerItemClickListener implements ListView.OnItemClickListener { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { selectItem(position); } } private void selectItem(int position) { Fragment fragment = new PlanetFragment(); Bundle args = new Bundle(); args.putInt(PlanetFragment.ARG_PLANET_NUMBER, position); fragment.setArguments(args);

FragmentManager fragmentManager = getFragmentManager(); fragmentManager.beginTransaction().replace(R.id.content_frame, fragment).commit();

mDrawerList.setItemChecked(position, true); setTitle(mPlanetTitles[position]); mDrawerLayout.closeDrawer(mDrawerList); }...

public class MainActivity extends Activity { private DrawerLayout mDrawerLayout; private ListView mDrawerList; private ActionBarDrawerToggle mDrawerToggle;

private CharSequence mDrawerTitle; private CharSequence mTitle; private String[] mPlanetTitles;

@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main);

mTitle = mDrawerTitle = getTitle(); mPlanetTitles = getResources().getStringArray(R.array.planets_array); mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout); mDrawerList = (ListView) findViewById(R.id.left_drawer);

mDrawerLayout.setDrawerShadow(R.drawable.drawer_shadow, GravityCompat.START); mDrawerList.setAdapter(new ArrayAdapter<String>(this, R.layout.drawer_list_item, mPlanetTitles)); mDrawerList.setOnItemClickListener(new DrawerItemClickListener());

getActionBar().setDisplayHomeAsUpEnabled(true); getActionBar().setHomeButtonEnabled(true);

mDrawerToggle = new ActionBarDrawerToggle( this, mDrawerLayout, R.drawable.ic_drawer, R.string.drawer_open, R.string.drawer_close ) { public void onDrawerClosed(View view) { getActionBar().setTitle(mTitle); invalidateOptionsMenu(); }

public void onDrawerOpened(View drawerView) { getActionBar().setTitle(mDrawerTitle); invalidateOptionsMenu(); } }; mDrawerLayout.setDrawerListener(mDrawerToggle);

if (savedInstanceState == null) { selectItem(0); } }...

Page 27: Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016

<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/drawer_layout" android:layout_width="match_parent" android:layout_height="match_parent">

<FrameLayout android:id="@+id/content_frame" android:layout_width="match_parent" android:layout_height="match_parent" />

<ListView android:id="@+id/left_drawer" android:layout_width="240dp" android:layout_height="match_parent" android:layout_gravity="start" android:choiceMode="singleChoice" android:divider="@android:color/transparent" android:dividerHeight="0dp" android:background="#111"/></android.support.v4.widget.DrawerLayout>

... @Override public boolean onPrepareOptionsMenu(Menu menu) { boolean drawerOpen = mDrawerLayout.isDrawerOpen(mDrawerList); menu.findItem(R.id.action_websearch).setVisible(!drawerOpen); return super.onPrepareOptionsMenu(menu); } @Override public void setTitle(CharSequence title) { mTitle = title; getActionBar().setTitle(mTitle); }

@Override protected void onPostCreate(Bundle savedInstanceState) { super.onPostCreate(savedInstanceState); mDrawerToggle.syncState(); }

@Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); mDrawerToggle.onConfigurationChanged(newConfig); }

public static class PlanetFragment extends Fragment { public static final String ARG_PLANET_NUMBER = "planet_number";

public PlanetFragment() {}

@Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View rootView = inflater.inflate(R.layout.fragment_planet, container, false); int i = getArguments().getInt(ARG_PLANET_NUMBER); String planet = getResources().getStringArray(R.array.planets_array)[i];

int imageId = getResources().getIdentifier(planet.toLowerCase(Locale.getDefault()), "drawable", getActivity().getPackageName()); ((ImageView) rootView.findViewById(R.id.image)).setImageResource(imageId); getActivity().setTitle(planet); return rootView; } }}

Page 28: Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016

onCreateonDrawerClosedonDrawerOpenedonPrepareOptionsMenuonCreateOptionsMenuonPostCreateonConfigurationChangedonCreateViewonOptionsItemSelectedonItemClickselectItem

MenuInflaterDrawerLayoutActionBarDrawerToggleBundleAdapterViewImageViewFragmentFragmentManagerPlanetFragment

Page 29: Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016
Page 30: Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016

App Store installs are broken !

?http://bit.ly/voxxrin

Page 31: Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016

App Store installs are broken !

Page 32: Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016

App Store installs are broken !

Page 33: Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016
Page 34: Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016
Page 35: Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016
Page 36: Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016

Ionic c’est quoi ?

+ =

Page 37: Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016

Stack technologique

Natif

Web

Téléphone & APIs natives

Cordova : webview +JavaScript bridges

Angular

Ionic

Application

Page 38: Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016

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

Page 39: Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016

DX#Platform continuity

#CLI

#Backend services

#Push

#Deploy

#Package#Auth

#Analytics #Ionic View

#Native plugins #Ionic Market

#Ionic Creator

Page 40: Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016

Ionic is a complete ecosystem !

Page 41: Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016

One more thing...

Page 42: Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016

Hybrid apps have superpowers...

Page 43: Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016

Hybrid superpowers

Page 44: Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016

Hybrid superpowers

Web App :

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

100 %

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

Page 45: Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016

Hybrid superpowers

Web App :

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

Progressive Web App :

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

Page 46: Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016

Hybrid superpowers

Web App :

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

Progressive Web App :

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

Native App :

● Accès complet au téléphone

Page 47: Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016

Hybrid superpowers

Page 48: Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016

App Store deployment is broken !

Google : ~ 2 heures

Apple : ~ 2 jours

Page 49: Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016

Hybrid superpowers

Page 50: Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016
Page 51: Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016
Page 52: Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016
Page 53: Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016
Page 54: Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016
Page 55: Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016
Page 56: Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016
Page 57: Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016
Page 58: Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016
Page 59: Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016
Page 60: Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016

Getting started

Install nodejs & npm

$ npm install -g ionic

$ ionic start demoApp --v2

$ cd demoApp && ionic serve

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

Page 61: Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016

Getting started

Install mobile sdk (Android ou iOS)

$ sudo npm install -g cordova

$ ionic run android

Page 62: Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016

src/index.html

<!DOCTYPE html><html lang="en" dir="ltr"><head> <meta charset="UTF-8"> <title>Ionic App</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 rel="icon" type="image/x-icon" href="assets/icon/favicon.ico"> <link rel="manifest" href="manifest.json"> <meta name="theme-color" content="#4e8ef7">

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

<script src="cordova.js"></script> <!-- cordova.js required for cordova apps --> <script src="build/polyfills.js"></script> <!-- polyfills generated during the build process --> <script src="build/main.js"></script> <!-- bundle generated during the build process --></body></html>

Page 63: Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016

src/app/main.dev.ts

import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';import { AppModule } from './app.module';

platformBrowserDynamic().bootstrapModule(AppModule);

Page 64: Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016

src/app/app.module.ts

import { NgModule } from '@angular/core';import { IonicApp, IonicModule } from 'ionic-angular';import { MyApp } from './app.component';import { HomePage } from '../pages/home/home';

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

Page 65: Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016

src/app/app.component.ts

import { Component } from '@angular/core';import { Platform } from 'ionic-angular';import { StatusBar } from 'ionic-native';import { HomePage } from '../pages/home/home';

@Component({ template: `<ion-nav [root]="rootPage"></ion-nav>`})export class MyApp { rootPage = HomePage;

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

Page 66: Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016

src/pages/home/home.ts

<ion-header> <ion-navbar> <ion-title>Ionic Blank</ion-title> </ion-navbar></ion-header>

<ion-content padding> The world is your oyster. <p> If you get lost, the <a href="http://ionicframework.com/docs/v2">docs</a> will be your guide. </p></ion-content>

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

@Component({ selector: 'page-home', templateUrl: 'home.html'})export class HomePage { constructor(public navCtrl: NavController) {}}

Page 67: Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016

src/pages/home/home.ts

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

@Component({ template: `<ion-header> <ion-navbar> <ion-title>Ionic Blank</ion-title> </ion-navbar></ion-header>

<ion-content padding> The world is your oyster. <p> If you get lost, the <a href="http://ionicframework.com/docs/v2">docs</a> will be your guide. </p></ion-content>`})export class HomePage { constructor(public navCtrl: NavController) {}}

Page 68: Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016
Page 69: Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016

$ ionic start todo-app --v2

Page 70: Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016

Créer une nouvelle page

$ ionic g page todo-list

Page 71: Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016

src/pages/todo-list

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

@Component({ selector: 'page-todo-list', templateUrl: 'todo-list.html'})export class TodoList { constructor(public navCtrl: NavController) {}

ionViewDidLoad() { console.log('Hello TodoList Page'); }}

<ion-header> <ion-navbar> <ion-title> todo-list </ion-title> </ion-navbar></ion-header>

<ion-content padding>

</ion-content>

page-todo-list {

}

todo-list.ts todo-list.html todo-list.scss

Page 72: Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016

import { NgModule } from '@angular/core';import { IonicApp, IonicModule } from 'ionic-angular';import { MyApp } from './app.component';import { HomePage } from '../pages/home/home';import { TodoList } from "../pages/todo-list/todo-list";

@NgModule({ declarations: [MyApp, HomePage, TodoList], imports: [IonicModule.forRoot(MyApp)], bootstrap: [IonicApp], entryComponents: [MyApp, HomePage, TodoList], providers: []})export class AppModule {}

import { Component } from '@angular/core';import { Platform } from 'ionic-angular';import { StatusBar } from 'ionic-native';import { TodoList } from "../pages/todo-list/todo-list";

@Component({ template: `<ion-nav [root]="rootPage"></ion-nav>`})export class MyApp { rootPage = TodoList;

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

src/app/app.module.ts src/app/app.component.ts

Page 73: Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016

Ionic2 TODO list

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

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

@Component({ selector: 'page-todo-list', templateUrl: 'todo-list.html'})export class TodoList { constructor(public navCtrl: NavController) {}}

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

<ion-content>

</ion-content>

Page 74: Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016

Ionic2 TODO list

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

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

@Component({ selector: 'page-todo-list', templateUrl: 'todo-list.html'})export class TodoList { todos: Todo[] = [ new Todo('todo 1'), new Todo('todo 2') ]; constructor(public navCtrl: NavController) {}}

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

<ion-content>

</ion-content>

Page 75: Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016

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

<ion-content> <ion-list> <ion-item *ngFor="let todo of todos"> {{todo.name}} </ion-item> </ion-list></ion-content>

Ionic2 TODO list

Page 76: Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016

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

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

Ionic2 TODO list

Page 77: Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016

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

<ion-content> <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-list></ion-content>

Ionic2 TODO list

Page 78: Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016

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

<ion-content> <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>{{todo.name}}</ion-label> <ion-checkbox [(ngModel)]="todo.done"></ion-checkbox> </ion-item> </ion-list></ion-content>

Ionic2 TODO list

Page 79: Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016

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

<ion-content> <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 disabled="true" checked></ion-checkbox> </ion-item> </ion-list></ion-content>

Ionic2 TODO list

Page 80: Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016

<ion-header> <ion-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 ion-button> <ion-icon name="send"></ion-icon> </button> </ion-buttons> </ion-toolbar></ion-header>

<ion-content> ...</ion-content>

Ionic2 TODO list

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

export class Todo { ... }

@Component({ selector: 'page-todo-list', templateUrl: 'todo-list.html'})export class TodoList { newTodo: string = ''; todos: Todo[] = [ ... ]; constructor(public navCtrl: NavController) {}}

Page 81: Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016

<ion-header> <ion-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 ion-button (click)="create(newTodo)"> <ion-icon name="send"></ion-icon> </button> </ion-buttons> </ion-toolbar></ion-header>

<ion-content> ...</ion-content>

Ionic2 TODO list

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

export class Todo { ... }

@Component({ selector: 'page-todo-list', templateUrl: 'todo-list.html'})export class TodoList { newTodo: string = ''; todos: Todo[] = [ ... ]; constructor(public navCtrl: NavController) {}

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

Page 82: Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016

<ion-header> <ion-navbar> <ion-title>Todos</ion-title> </ion-navbar> <ion-toolbar> ... </ion-toolbar></ion-header>

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

Ionic2 TODO list

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

export class Todo { ... }

@Component({ selector: 'page-todo-list', templateUrl: 'todo-list.html'})export class TodoList { newTodo: string = ''; todos: Todo[] = [ ... ]; constructor(public navCtrl: NavController) {}

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

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

Page 83: Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016
Page 84: Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016

Créer un composant

$ ionic g component todo-item

Page 85: Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016

src/components/todo-item

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

@Component({ selector: 'todo-item', templateUrl: 'todo-item.html'})export class TodoItem { text: string;

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

{{text}} todo-item {

}

todo-item.ts todo-item.html todo-item.scss

Page 86: Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016

import { NgModule } from '@angular/core';import { IonicApp, IonicModule } from 'ionic-angular';import { MyApp } from './app.component';import { HomePage } from '../pages/home/home';import { TodoList } from '../pages/todo-list/todo-list';import { TodoItem } from "../components/todo-item/todo-item";

@NgModule({ declarations: [MyApp, HomePage, TodoList, TodoItem], imports: [IonicModule.forRoot(MyApp)], bootstrap: [IonicApp], entryComponents: [MyApp, HomePage, TodoList], providers: []})export class AppModule {}

src/app/app.module.ts

Page 87: Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016

src/components/todo-item

import { Component, Input } from '@angular/core';import {Todo} from '../../pages/todo-list/todo-list';

@Component({ selector: 'todo-item', templateUrl: 'todo-item.html'})export class TodoItem { @Input() todo: Todo; constructor() {}}

{{text}}

Page 88: Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016

src/components/todo-item

import { Component, Input } from '@angular/core';import {Todo} from '../../pages/todo-list/todo-list';

@Component({ selector: 'todo-item', templateUrl: 'todo-item.html'})export class TodoItem { @Input() todo: Todo; constructor() {}}

<ion-item> <ion-label> {{todo.name}} </ion-label> <ion-checkbox [(ngModel)]="todo.done"></ion-checkbox></ion-item>

Page 89: Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016

src/components/todo-item

import { Component, Input } from '@angular/core';import {Todo} from '../../pages/todo-list/todo-list';

@Component({ selector: 'todo-item', templateUrl: 'todo-item.html'})export class TodoItem { @Input() todo: Todo; constructor() {}}

<ion-item> <ion-label [class.done]="todo.done"> {{todo.name}} </ion-label> <ion-checkbox [(ngModel)]="todo.done" [disabled]="todo.done" [checked]="todo.done"></ion-checkbox></ion-item>

Page 90: Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016

<ion-content> <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" (click)="remove(todo)"> <ion-label class="done">{{todo.name}}</ion-label> <ion-checkbox disabled="true" checked></ion-checkbox> </ion-item> </ion-list></ion-content>

todo-list.html

Page 91: Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016

<ion-content> <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" (click)="remove(todo)"> <ion-label class="done">{{todo.name}}</ion-label> <ion-checkbox disabled="true" checked></ion-checkbox> </ion-item> </ion-list></ion-content>

<ion-content> <ion-list> <todo-item *ngFor="let todo of todos" [todo]="todo" [hidden]="todo.done"></todo-item> <todo-item *ngFor="let todo of todos" [todo]="todo" [hidden]="!todo.done" (click)="remove(todo)"></todo-item> </ion-list></ion-content>

todo-list.html

Page 92: Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016
Page 93: Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016

Créer un service

$ ionic g provider todo-service

Page 94: Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016

import { Injectable } from '@angular/core';import { Http } from '@angular/http';import 'rxjs/add/operator/map';

@Injectable()export class TodoService { constructor(public http: Http) { console.log('Hello TodoService Provider'); }}

src/providers/todo-service.ts

Page 95: Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016

import { NgModule } from '@angular/core';import { IonicApp, IonicModule } from 'ionic-angular';import { MyApp } from './app.component';import { HomePage } from '../pages/home/home';import { TodoList } from "../pages/todo-list/todo-list";import { TodoItem } from "../components/todo-item/todo-item";import { TodoService } from "../providers/todo-service";

@NgModule({ declarations: [MyApp, HomePage, TodoList, TodoItem], imports: [IonicModule.forRoot(MyApp)], bootstrap: [IonicApp], entryComponents: [MyApp, HomePage, TodoList], providers: [TodoService]})export class AppModule {}

src/app/app.module.ts

Page 96: Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016

import { Injectable } from '@angular/core';import 'rxjs/add/operator/map';import {Todo} from "../pages/todo-list/todo-list";

@Injectable()export class TodoService { constructor() {} private todos: Todo[] = [ new Todo('todo 1'), new Todo('todo 2') ]; getTodos(): Todo[] { return this.todos; } createTodo(text: string): void { this.todos.push(new Todo(text)); } removeTodo(todo: Todo): void { const i = this.todos.indexOf(todo); if(i >= 0) { this.todos.splice(i, 1); } }}

src/providers/todo-service.ts

Page 97: Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016

import { Component } from '@angular/core';import { TodoService } from "../../providers/todo-service";

@Component({ selector: 'page-todo-list', templateUrl: 'todo-list.html'})export class TodoList { newTodo: string = ''; todos: Todo[] = []; constructor(private todoSrv: TodoService) { this.todos = todoSrv.getTodos(); }

create(text: string): void { this.todoSrv.createTodo(text); this.newTodo = ''; } remove(todo: Todo): void { this.todoSrv.removeTodo(todo); }}

src/pages/todo-list/todo-list.ts

Page 98: Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016
Page 99: Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016

Ionic2 Menu

$ ionic start my-app sidemenu --v2

Page 100: Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016

<ion-menu [content]="content"> <ion-header> <ion-toolbar> <ion-title>Menu</ion-title> </ion-toolbar> </ion-header> <ion-content> <ion-list> <button ion-item menuClose *ngFor="let p of pages" (click)="openPage(p)"> {{p.title}} </button> </ion-list> </ion-content></ion-menu>

<ion-nav [root]="rootPage" #content></ion-nav>

@Component({ templateUrl: 'app.html'})export class MyApp { @ViewChild(Nav) nav: Nav; rootPage: any = Page1; pages: {title: string, component: any}[];

constructor(public platform: Platform) { this.pages = [ { title: 'Page One', component: Page1 }, { title: 'Page Two', component: Page2 } ]; }

openPage(page) { this.nav.setRoot(page.component); }}

Ionic2 Sidemenu

Page 101: Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016

<ion-menu [content]="content"> <ion-header> <ion-toolbar> <ion-title>Menu</ion-title> </ion-toolbar> </ion-header> <ion-content> <ion-list> <button menuClose ion-item (click)="openPage1()"> Page One </button> <button menuClose ion-item (click)="openPage2()"> Page Two </button> </ion-list> </ion-content></ion-menu>

<ion-nav [root]="rootPage" #content></ion-nav>

@Component({ templateUrl: 'app.html'})export class MyApp { @ViewChild(Nav) nav: Nav; rootPage: any = Page1; constructor(public platform: Platform) {}

openPage1() { this.nav.setRoot(Page1); } openPage2() { this.nav.setRoot(Page2); }}

Ionic2 Sidemenu

Page 102: Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016

<ion-menu [content]="content"> <ion-header> <ion-toolbar> <ion-title>Menu</ion-title> </ion-toolbar> </ion-header> <ion-content> <ion-list> <button menuClose ion-item (click)="openPage1()"> Page One </button> <button menuClose ion-item (click)="openPage2()"> Page Two </button> </ion-list> </ion-content></ion-menu>

<ion-nav [root]="rootPage" #content></ion-nav>

@Component({ templateUrl: 'app.html'})export class MyApp { @ViewChild(Nav) nav: Nav; rootPage: any = Page1; constructor(public platform: Platform) {}

openPage1() { this.nav.setRoot(Page1); } openPage2() { this.nav.setRoot(Page2); }}

Ionic2 Sidemenu

22 lignesvs

137 lignes !!!

Page 103: Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016

Pour tester ce weekend...

Page 105: Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016
Page 106: Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016

Questions ?

@loicknuchel