Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
The rise of web developers
le 21/10/2016, ionic 2.0-rc1 @loicknuchel
Loïc Knuchel
Geek passionné
Développeur Scala
Organisateur
loicknuchel@gmail.com
@loicknuchel
http://loic.knuchel.org/
L’histoire du smartphone
Juin 2007
Lancement de l’iPhone 1
Septembre 2008
Sortie du HTC G1
avec 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éc...
La WebView
Idée
Coder des applications
entièrement dans la WebView
Idée
Coder des applications
entièrement dans la WebView
Avantages :
● Cross-platform
● Technologies et environnements conn...
PhoneGap / Cordova
Mars 2009 :
Lancement de PhoneGap par Nitobi
Octobre 2011 :
Rachat de Nitobi par Adobe
Séparation de la...
Oups...
● UI moche
● UI peu réactive
● loin du look & feel natif
Mauvais support des standards du
web dans la WebView
Peu ...
Aujourd’hui
● Téléphones puissants (et de + en +)
● Très bon support des standards web dans la WebView
● Beaucoup d’outils...
Native develoment is ...
way ...
Performance
Code re-write
Complicated
Android Menu (Nav Drawer)
Source: https://developer.android.com/training/implementing-navigation/nav-drawer.html
...
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(...
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/drawer...
onCreate
onDrawerClosed
onDrawerOpened
onPrepareOptionsMenu
onCreateOptionsMenu
onPostCreate
onConfigurationChanged
onCrea...
App Store installs are broken !
?
http://bit.ly/voxxrin
App Store installs are broken !
App Store installs are broken !
Ionic c’est quoi ?
+ =
Stack technologique
Natif
Web
Téléphone & APIs natives
Cordova : webview +
JavaScript bridges
Angular
Ionic
Application
DX
“We want to cater to the 99% who just want to build something functional quickly
and not break the bank to do it.” - Ma...
DX
#Platform continuity
#CLI
#Backend services
#Push
#Deploy
#Package
#Auth
#Analytics #Ionic View
#Native plugins
#Ionic ...
Ionic is a complete ecosystem !
One more thing...
Hybrid apps have superpowers...
Hybrid superpowers
●
Hybrid superpowers
Web App :
● Cross-platform
● Searchable
● Accès instantané
● Deep link
100 %
http://bit.ly/voxxrin-bdx-...
Hybrid superpowers
Web App :
● Cross-platform
● Searchable
● Accès instantané
● Deep link
Progressive Web App :
● Installa...
Hybrid superpowers
Web App :
● Cross-platform
● Searchable
● Accès instantané
● Deep link
Progressive Web App :
● Installa...
Hybrid superpowers
●
App Store deployment is broken !
Google : ~ 2 heures
Apple : ~ 2 jours
Hybrid superpowers
●
Getting started
Install nodejs & npm
$ npm install -g ionic
$ ionic start demoApp --v2
$ cd demoApp && ionic serve
♬ ♫ ♬ ♫...
Getting started
Install mobile sdk (Android ou iOS)
$ sudo npm install -g cordova
$ ionic run android
src/index.html
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="UTF-8">
<title>Ionic App</title>
<meta nam...
src/app/main.dev.ts
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from ...
src/app/app.module.ts
import { NgModule } from '@angular/core';
import { IonicApp, IonicModule } from 'ionic-angular';
imp...
src/app/app.component.ts
import { Component } from '@angular/core';
import { Platform } from 'ionic-angular';
import { Sta...
src/pages/home/home.ts
<ion-header>
<ion-navbar>
<ion-title>Ionic Blank</ion-title>
</ion-navbar>
</ion-header>
<ion-conte...
src/pages/home/home.ts
import { Component } from '@angular/core';
import { NavController } from 'ionic-angular';
@Componen...
$ ionic start todo-app --v2
Créer une nouvelle page
$ ionic g page todo-list
src/pages/todo-list
import { Component } from '@angular/core';
import { NavController } from 'ionic-angular';
@Component({...
import { NgModule } from '@angular/core';
import { IonicApp, IonicModule } from
'ionic-angular';
import { MyApp } from './...
Ionic2 TODO list
import { Component } from '@angular/core';
import { NavController } from 'ionic-angular';
export class To...
Ionic2 TODO list
import { Component } from '@angular/core';
import { NavController } from 'ionic-angular';
export class To...
<ion-header>
<ion-navbar>
<ion-title>Todos</ion-title>
</ion-navbar>
</ion-header>
<ion-content>
<ion-list>
<ion-item *ngF...
<ion-header>
<ion-navbar>
<ion-title>Todos</ion-title>
</ion-navbar>
</ion-header>
<ion-content>
<ion-list>
<ion-item *ngF...
<ion-header>
<ion-navbar>
<ion-title>Todos</ion-title>
</ion-navbar>
</ion-header>
<ion-content>
<ion-list>
<ion-item *ngF...
<ion-header>
<ion-navbar>
<ion-title>Todos</ion-title>
</ion-navbar>
</ion-header>
<ion-content>
<ion-list>
<ion-item *ngF...
<ion-header>
<ion-navbar>
<ion-title>Todos</ion-title>
</ion-navbar>
</ion-header>
<ion-content>
<ion-list>
<ion-item *ngF...
<ion-header>
<ion-navbar><ion-title>Todos</ion-title></ion-navbar>
<ion-toolbar>
<ion-input type="text" [(ngModel)]="newTo...
<ion-header>
<ion-navbar>
<ion-title>Todos</ion-title>
</ion-navbar>
<ion-toolbar>
<ion-input type="text" [(ngModel)]="new...
<ion-header>
<ion-navbar>
<ion-title>Todos</ion-title>
</ion-navbar>
<ion-toolbar>
...
</ion-toolbar>
</ion-header>
<ion-c...
Créer un composant
$ ionic g component todo-item
src/components/todo-item
import { Component } from '@angular/core';
@Component({
selector: 'todo-item',
templateUrl: 'todo...
import { NgModule } from '@angular/core';
import { IonicApp, IonicModule } from 'ionic-angular';
import { MyApp } from './...
src/components/todo-item
import { Component, Input } from
'@angular/core';
import {Todo} from
'../../pages/todo-list/todo-...
src/components/todo-item
import { Component, Input } from
'@angular/core';
import {Todo} from
'../../pages/todo-list/todo-...
src/components/todo-item
import { Component, Input } from
'@angular/core';
import {Todo} from
'../../pages/todo-list/todo-...
<ion-content>
<ion-list>
<ion-item *ngFor="let todo of todos" [hidden]="todo.done">
<ion-label>{{todo.name}}</ion-label>
<...
<ion-content>
<ion-list>
<ion-item *ngFor="let todo of todos" [hidden]="todo.done">
<ion-label>{{todo.name}}</ion-label>
<...
Créer un service
$ ionic g provider todo-service
import { Injectable } from '@angular/core';
import { Http } from '@angular/http';
import 'rxjs/add/operator/map';
@Injecta...
import { NgModule } from '@angular/core';
import { IonicApp, IonicModule } from 'ionic-angular';
import { MyApp } from './...
import { Injectable } from '@angular/core';
import 'rxjs/add/operator/map';
import {Todo} from "../pages/todo-list/todo-li...
import { Component } from '@angular/core';
import { TodoService } from "../../providers/todo-service";
@Component({
select...
Ionic2 Menu
$ ionic start my-app sidemenu --v2
<ion-menu [content]="content">
<ion-header>
<ion-toolbar>
<ion-title>Menu</ion-title>
</ion-toolbar>
</ion-header>
<ion-co...
<ion-menu [content]="content">
<ion-header>
<ion-toolbar>
<ion-title>Menu</ion-title>
</ion-toolbar>
</ion-header>
<ion-co...
<ion-menu [content]="content">
<ion-header>
<ion-toolbar>
<ion-title>Menu</ion-title>
</ion-toolbar>
</ion-header>
<ion-co...
Pour tester ce weekend...
Pour tester ce weekend...
http://ionicframework.com/docs/v2/
https://github.com/driftyco/ionic-conference-app
https://gith...
Questions ?
@loicknuchel
Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016
Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016
Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016
Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016
Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016
Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016
Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016
Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016
Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016
Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016
Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016
Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016
Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016
Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016
Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016
Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016
Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016
Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016
Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016
Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016
Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016
Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016
Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016
Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016
Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016
Upcoming SlideShare
Loading in …5
×

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

272 views

Published on

Le mobile est maintenant majoritaire et continue toujours de croître. Mais son écosystème technique est encore très spécifique et demande des compétences pointues. Venez découvrir Ionic, le framework d’UI qui permet aux développeurs web de faire des applications mobiles de qualité avec des technologies web.

Published in: Software
  • Be the first to comment

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

  1. 1. The rise of web developers le 21/10/2016, ionic 2.0-rc1 @loicknuchel
  2. 2. Loïc Knuchel Geek passionné Développeur Scala Organisateur loicknuchel@gmail.com @loicknuchel http://loic.knuchel.org/
  3. 3. L’histoire du smartphone
  4. 4. Juin 2007 Lancement de l’iPhone 1
  5. 5. Septembre 2008 Sortie du HTC G1 avec Android
  6. 6. ● Nouvelles possibilités ○ UX ○ Technique ○ Business ● Un écosystème à bâtir
  7. 7. ● 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é...)
  8. 8. La WebView
  9. 9. Idée Coder des applications entièrement dans la WebView
  10. 10. Idée Coder des applications entièrement dans la WebView Avantages : ● Cross-platform ● Technologies et environnements connus
  11. 11. PhoneGap / Cordova Mars 2009 : Lancement de PhoneGap par Nitobi Octobre 2011 : Rachat de Nitobi par Adobe Séparation de la technologie (Cordova) et des services commerciaux (PhoneGap)
  12. 12. 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...
  13. 13. Aujourd’hui ● Téléphones puissants (et de + en +) ● Très bon support des standards web dans la WebView ● Beaucoup d’outils / librairies
  14. 14. Native develoment is ...
  15. 15. way ...
  16. 16. Performance
  17. 17. Code re-write
  18. 18. Complicated
  19. 19. Android Menu (Nav Drawer) Source: https://developer.android.com/training/implementing-navigation/nav-drawer.html
  20. 20. ... @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); } } ...
  21. 21. <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; } } }
  22. 22. onCreate onDrawerClosed onDrawerOpened onPrepareOptionsMenu onCreateOptionsMenu onPostCreate onConfigurationChanged onCreateView onOptionsItemSelected onItemClick selectItem MenuInflater DrawerLayout ActionBarDrawerToggle Bundle AdapterView ImageView Fragment FragmentManager PlanetFragment
  23. 23. App Store installs are broken ! ? http://bit.ly/voxxrin
  24. 24. App Store installs are broken !
  25. 25. App Store installs are broken !
  26. 26. Ionic c’est quoi ? + =
  27. 27. Stack technologique Natif Web Téléphone & APIs natives Cordova : webview + JavaScript bridges Angular Ionic Application
  28. 28. 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
  29. 29. DX #Platform continuity #CLI #Backend services #Push #Deploy #Package #Auth #Analytics #Ionic View #Native plugins #Ionic Market #Ionic Creator
  30. 30. Ionic is a complete ecosystem !
  31. 31. One more thing...
  32. 32. Hybrid apps have superpowers...
  33. 33. Hybrid superpowers ●
  34. 34. Hybrid superpowers Web App : ● Cross-platform ● Searchable ● Accès instantané ● Deep link 100 % http://bit.ly/voxxrin-bdx-lkn
  35. 35. 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
  36. 36. 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
  37. 37. Hybrid superpowers ●
  38. 38. App Store deployment is broken ! Google : ~ 2 heures Apple : ~ 2 jours
  39. 39. Hybrid superpowers ●
  40. 40. Getting started Install nodejs & npm $ npm install -g ionic $ ionic start demoApp --v2 $ cd demoApp && ionic serve ♬ ♫ ♬ ♫ Your Ionic app is ready to go! ♬ ♫ ♬ ♫
  41. 41. Getting started Install mobile sdk (Android ou iOS) $ sudo npm install -g cordova $ ionic run android
  42. 42. 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>
  43. 43. src/app/main.dev.ts import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; import { AppModule } from './app.module'; platformBrowserDynamic().bootstrapModule(AppModule);
  44. 44. 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 {}
  45. 45. 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(); }); } }
  46. 46. 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) {} }
  47. 47. 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) {} }
  48. 48. $ ionic start todo-app --v2
  49. 49. Créer une nouvelle page $ ionic g page todo-list
  50. 50. 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
  51. 51. 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
  52. 52. 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>
  53. 53. 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>
  54. 54. <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
  55. 55. <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
  56. 56. <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
  57. 57. <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
  58. 58. <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
  59. 59. <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) {} }
  60. 60. <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 = ''; } }
  61. 61. <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); } } }
  62. 62. Créer un composant $ ionic g component todo-item
  63. 63. 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
  64. 64. 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
  65. 65. 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}}
  66. 66. 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>
  67. 67. 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>
  68. 68. <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
  69. 69. <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
  70. 70. Créer un service $ ionic g provider todo-service
  71. 71. 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
  72. 72. 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
  73. 73. 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
  74. 74. 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
  75. 75. Ionic2 Menu $ ionic start my-app sidemenu --v2
  76. 76. <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
  77. 77. <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
  78. 78. <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 lignes vs 137 lignes !!!
  79. 79. Pour tester ce weekend...
  80. 80. Pour tester ce weekend... http://ionicframework.com/docs/v2/ https://github.com/driftyco/ionic-conference-app https://github.com/saloonapp/saloon-app http://mcgivery.com/15-ionic-framework-2-resources/ (60+ maintenant…) https://angular.io/docs/ts/latest/cookbook/ https://forum.ionicframework.com/
  81. 81. Questions ? @loicknuchel

×