Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016
-
Upload
loic-knuchel -
Category
Software
-
view
165 -
download
2
Transcript of 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
Loïc KnuchelGeek passionné
Développeur Scala
Organisateur
@loicknuchel
http://loic.knuchel.org/
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
Idée
Coder des applicationsentièrement dans la WebView
Avantages :
● Cross-platform● Technologies et environnements connus
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
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(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); } }...
<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; } }}
onCreateonDrawerClosedonDrawerOpenedonPrepareOptionsMenuonCreateOptionsMenuonPostCreateonConfigurationChangedonCreateViewonOptionsItemSelectedonItemClickselectItem
MenuInflaterDrawerLayoutActionBarDrawerToggleBundleAdapterViewImageViewFragmentFragmentManagerPlanetFragment
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.” - Max Lynch
DX#Platform continuity
#CLI
#Backend services
#Push
#Deploy
#Package#Auth
#Analytics #Ionic View
#Native plugins #Ionic Market
#Ionic Creator
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-lkn
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
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
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
♬ ♫ ♬ ♫ Your Ionic app is ready to go! ♬ ♫ ♬ ♫
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 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>
src/app/main.dev.ts
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';import { AppModule } from './app.module';
platformBrowserDynamic().bootstrapModule(AppModule);
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 {}
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(); }); }}
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) {}}
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) {}}
$ 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({ 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
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
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>
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>
<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
<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
<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
<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
<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
<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) {}}
<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 = ''; }}
<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); } }}
Créer un composant
$ ionic g component todo-item
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
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
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}}
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>
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>
<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
<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
Créer un service
$ ionic g provider todo-service
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
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
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
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
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-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
<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
<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 !!!
Pour tester ce weekend...
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/
Questions ?
@loicknuchel