Ionic 2 - Hybridapps auf Steroiden

91
Ionic 2 HYBRID APPS AUF STEROIDEN

Transcript of Ionic 2 - Hybridapps auf Steroiden

Page 1: Ionic 2 - Hybridapps auf Steroiden

Ionic 2HYBRID APPS AUF STEROIDEN

Page 2: Ionic 2 - Hybridapps auf Steroiden
Page 3: Ionic 2 - Hybridapps auf Steroiden

InhalteProjektumgebung- Build- Debugging- Testautomatisierung- Externe Bibliotheken nutzen

Vorgehen- Bottom Up- Test First- Top Down

Ionic Services- Welche Dienste?- Wie eingesetzt?- Wie tragfähig?

Ionic- Projektstruktur- Wichtige Komponenten- Client Server Kommunikation- Promises- Lifecycle Hooks- Navigation- Tabs- Modals- Formulare- Toasts- Locale Storage- Plugins

Page 4: Ionic 2 - Hybridapps auf Steroiden

Szenario

Search Favorites About

Details

Tabs

Input

Page 5: Ionic 2 - Hybridapps auf Steroiden

Installation und Vorbereitung

Page 7: Ionic 2 - Hybridapps auf Steroiden

http://cmder.net/

Page 8: Ionic 2 - Hybridapps auf Steroiden

1. npm installieren: nodejs.org/en/download/

2. npm install –g cordova

3. npm install –g ionic

4. npm install –g typings

Page 9: Ionic 2 - Hybridapps auf Steroiden

Was ist Ionic?

?!?

Page 10: Ionic 2 - Hybridapps auf Steroiden
Page 11: Ionic 2 - Hybridapps auf Steroiden
Page 12: Ionic 2 - Hybridapps auf Steroiden
Page 13: Ionic 2 - Hybridapps auf Steroiden

Die CLI

Bild durch Klicken auf Symbol hinzufügen

Page 14: Ionic 2 - Hybridapps auf Steroiden

npm --version Version con NPM abrufennpm help {befehl} Ruft die Hilfe für den entsprechenden Befehl aufnpm install [-g] {Paketname} Installiert das Paket im aktuellen Projekt bzw. globalnpm install {Paketname}@{Version} Installiert das Paket mit der entsprechenden Version in das aktuelle Projekt.

--save Das Paket wird in die Liste der Abhängigkeiten des Projekts eingetragen

--save-dev Das Paket wird in die Liste der Abhängigkeiten des Projekts eingetragen die zur Entwicklungszeit gelten.

--force Das Paket wird installiert selbst wenn es schon vorhanden ist.npm list Zeigt alle installierten Pakete im aktuellen Projekt an.npm view {Paketname} Ruft diverse Informationen zum angegebenen Paket ab.npm view {Paketname} {Detailbezeichnung} Ruft nur die Detailinformationen ab (bspw. Versions)

npm update Aktualisiert alle Pakete des aktuellen Projekts die als Abhängigkeiten gespeichert wurden.

npm update [-g] {Paketname}[@{Version}] Aktualisiert das gegebene Paket ggf. auf eine bestimmte Version oder auf die neuste.

npm uninstall {Paketname} Deinstalliert das angegebene Paket.--save Entfernt das Paket aus den Projektabhängigkeiten.--save-dev Entfernt das Paket aus den Projektabhängigkeiten für die Entwicklungszeit.

Die wichtigsten Befehle für NPM im Kontext von Ionic

Page 15: Ionic 2 - Hybridapps auf Steroiden

ionic start {AppName} blank --v2 Leeres Projekt für Ionic 2 erstellen.

ionic start {AppName} tabs Projekt mit Tab Template für Ionic 1 erstellen.ionic start {AppName} sidemenu Projekt mit Sidemenu Template für Ionic 1 erstellen.ionic platform add android/ios Android bzw. iOs als Plattform hinzufügen.ionic platform list Zeigt alle installierten Plattformen an.Ionic platform remove {platform} Entfern die angegebene Plattform.

ionic build android/ios Plattform bauen.ionic emulate android/ios Plattformversion im Emulator starten.ionic run android/ios Plattformversion auf Gerät starten.ionic serve

--lab--consolelogs |-c--serverlogs |-s

App im Browser ausführen.App im Browser mit Ansichten für iOS und Android ausführen.Ausgabe des Consolen loggings in der CLI.Server Logs in der CLI ausgeben.

ionic login Bei den Ionic Services anmelden.ionic upload Die aktuelle App in die Ionic Cloud hochladen.ionic share Die aktuelle App über die Ionic Cloud mit anderen Personen teilen.ionic --help Auflistung und Erläuterung aller CLI Befehle.

cordova clean Entfernt alle

Die wichtigsten Befehle für Ionic und Cordova

Page 16: Ionic 2 - Hybridapps auf Steroiden

Die App bauen

Page 17: Ionic 2 - Hybridapps auf Steroiden

Infrastruktur aufsetzen

Page 18: Ionic 2 - Hybridapps auf Steroiden

Ionic start myApp –v2 blank

Page 19: Ionic 2 - Hybridapps auf Steroiden

cd {app name} ionic serve --lab

Page 20: Ionic 2 - Hybridapps auf Steroiden

Jede Seite erhält ein Verzeichnis mit: - Darstellung .html- Styles .scss- Logik .ts

Page 21: Ionic 2 - Hybridapps auf Steroiden

Applikationsweite Einstellungen können plattformspezifisch konfiguriert werden.

Page 22: Ionic 2 - Hybridapps auf Steroiden

Das Bootstrapping wird an zentraler Stelle verwaltet und beim Programmstart eingeleitet.

Page 23: Ionic 2 - Hybridapps auf Steroiden

Cordova plugins werden zentral gespeichert und direkt über Ionic verwendet.

Es gibt kein ngCordova!

Page 24: Ionic 2 - Hybridapps auf Steroiden

Cordova Plugins u.ä. werden über Hooks in die Applikation eingebunden.

Dies geschieht weitestgehend automatisch.

Page 25: Ionic 2 - Hybridapps auf Steroiden

Ionic speichert alle wichtigen Bibliotheken und Frameworks zunächst im node_modues Verzeichnis.

Zusätzliche Pakete sollten IMMER über NPM installiert werden damit der Buildprozess korrekt fuktioniert!

Page 26: Ionic 2 - Hybridapps auf Steroiden

Splash screens und App Icons können für jedes plattform gesondert angegeben werden.

Sie werden über die CLI aus einer Vorlage heraus generiert.

Page 27: Ionic 2 - Hybridapps auf Steroiden

Type Script 1.x benötigt Typeings um Javascript Frameworks ansprechen zu können.Diese sind separat mit jedem Framework herunter zu laden.

Page 28: Ionic 2 - Hybridapps auf Steroiden

Die eigentliche App wird nach einem ionic build im www Verzeichnis zur Verfügung gestellt.

Im www Verzeichnis sollte nicht entwickelt werden!!!

Page 29: Ionic 2 - Hybridapps auf Steroiden

Konfiguration aller wichtigen Umgebungsparameter der App (Version, App Package, API Version, …)

Konfiguration des Buildprozesses

Konfiguration der Ionic Parameter (welche Ionic Version, wird typscript verwendet, …)

NPM und Cordova Config (welche Pakete werden verwendet, Plattformen addressiert, Plugins verwendet)

Konfiguration des Typescript Transpilings (in welche JS Version, welche Dateien, wo liegen die Typings)

Konfiguration des Linters zur statischen Codeanalyse

Registrierung der eigentlichen Typings

Page 30: Ionic 2 - Hybridapps auf Steroiden

<?xml version="1.0" encoding="UTF-8"?><widget xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0" id="de.MovieManiaProductions.MoviewMania" version="1.0.0"> <name>movieMania</name> <description>An Ionic Framework and Cordova project.</description> <author email="hi@ionicframework" href="http://ionicframework.com/">Ionic Framework Team</author> <content src="index.html" /> <access origin="*" /> <allow-intent href="http://*/*" /> <allow-intent href="https://*/*" /> <allow-intent href="tel:*" /> <allow-intent href="sms:*" /> <allow-intent href="mailto:*" /> <allow-intent href="geo:*" /> <platform name="android"> <allow-intent href="market:*" /> </platform> <platform name="ios"> <allow-intent href="itms:*" /> <allow-intent href="itms-apps:*" /> </platform> <preference name="webviewbounce" value="false" /> <preference name="UIWebViewBounce" value="false" /> <preference name="DisallowOverscroll" value="true" /> … <feature name="StatusBar"> <param name="ios-package" onload="true" value="CDVStatusBar" /> </feature> <plugin name="cordova-plugin-device" spec="~1.1.3" /> <plugin name="cordova-plugin-console" spec="~1.0.4" /> …</widget>

Package ID darf sich zukünftig nicht mehr ändern!!!

Entspricht der Version im Store!

Page 31: Ionic 2 - Hybridapps auf Steroiden

Testinfrastruktur hinzufügen

Page 32: Ionic 2 - Hybridapps auf Steroiden

npm install karma --save-dev

npm install -g karma-cli

karma init karma.conf.js

Page 33: Ionic 2 - Hybridapps auf Steroiden

1. Ersetze karma.conf.js durch: https://github.com/HerrLoesch/IonicWorkshop/blob/master/karma.conf.js

2. Füge folgende Abhänigkeiten in der package.json hinzu: "jasmine-core": "^2.4.1",

"karma": "^0.13.22",

"karma-chrome-launcher": "^1.0.1",

"karma-jasmine": "^1.0.2",

"run-sequence": "1.1.5",

"karma-browserify": "5.0.5",

"browserify": "13.0.0",

"browserify-istanbul": "2.0.0",

"tsify": "0.16.0",

"isparta": "4.0.0"

"scripts": {

"test": "karma start karma.conf.js --browsers=Chrome --single-run=false --debug"

},

3. Ergänze folgendes Script in package.json:

Page 34: Ionic 2 - Hybridapps auf Steroiden

Komponente erzeugen mit der wir die Daten auslesen:

ionic g provider Movies

Page 35: Ionic 2 - Hybridapps auf Steroiden

import {beforeEachProviders, it, describe, expect, inject} from '@angular/core/testing';import {Movies} from './movies'; describe('movie services', () => { it('should return true', () => { expect(true).toBeTruthy(); }); });

1. Füge neue Datei hinzu movies.spec.ts

2. Schreibe folgenden Inhalt in die Datei:

3. npm test-> Test sollte erfolgreich sein

4. Ändere im test expect(true) zu expect(false)-> Test sollte fehlschlagen

Page 36: Ionic 2 - Hybridapps auf Steroiden

npm install karma-htmlfile-reporter --save-dev

karma.conf.js erweitern:

module.exports = function(config) {  config.set({    reporters: ['progress', 'html'],     htmlReporter: {      outputFile: 'test/results.html',                  // Optional       pageTitle: ‚Moview Mania',      subPageTitle: 'Test results',      groupSuites: true,      useCompactStyle: true,      useLegacyStyle: true    }  });};

Html Report

Page 37: Ionic 2 - Hybridapps auf Steroiden

Debuggen mit Chromenpm test

F12

ts Datei wählen

Break Point setzen

F5

Page 38: Ionic 2 - Hybridapps auf Steroiden

Augury

Page 39: Ionic 2 - Hybridapps auf Steroiden

Externe Bibliotheken laden

Page 40: Ionic 2 - Hybridapps auf Steroiden

Beispiel lodash

npm install -g typings

npm install lodash --savetypings install lodash –save

import {[Funktionen die verwendet werden]} from 'lodash';

Überall wo es verwendet wird

Page 41: Ionic 2 - Hybridapps auf Steroiden

Die SucheTest First & Bottom Up

Search Favorites About

Details

Tabs

Input

Page 42: Ionic 2 - Hybridapps auf Steroiden

http://www.omdbapi.com/

Page 43: Ionic 2 - Hybridapps auf Steroiden

import {beforeEachProviders, it, describe, expect, inject} from '@angular/core/testing';import {Movies} from './movies';import {includes, find} from 'lodash'; describe('movie search', () => { beforeEachProviders(() => [Movies]);

it('should return an array of movies for the search text lo', inject([Movies], (movieRepository) =>{ var movies = movieRepository.search("lo");

expect(Array.isArray(movies)).toBeTruthy; expect(movies.length).toBeGreaterThan(0); }));

[2. Test]});

Der 1. Test

Page 44: Ionic 2 - Hybridapps auf Steroiden

Der (Fake)Provider + Domain Objectimport { Injectable } from '@angular/core';import 'rxjs/add/operator/map';

@Injectable()export class Movies {

constructor() {}

public search(searchText: string) { let data = new Array();

let movie = {}; movie.Title = "olo";

data.push(movie); return data;

}}

export class Movie { public Title : string; public Year : number; public imdbID: string; public Type: string; public Poster: string;

}

Beispiel: http://www.omdbapi.com/?s=lo

{ "Title":"The Hi-Lo Country", "Year":"1998", "imdbID":"tt0120699", "Type":"movie", "Poster":"https://images-na.ssl-images-...},

Page 45: Ionic 2 - Hybridapps auf Steroiden

Quelle: http://www.joshmorony.com/an-in-depth-explanation-of-providers-in-ionic-2/

Was ist ein Provider

Page 46: Ionic 2 - Hybridapps auf Steroiden

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

@Injectable()export class Movies {

constructor(private http: Http) {}

public search(searchText: string) {

return new Promise(resolve => { let url = 'http://www.omdbapi.com/?s=' + searchText; console.log('start searching:' + url);

this.http.get(url) .map(result => result.json()) .subscribe(data => resolve(data.Search));

});}

}

Page 47: Ionic 2 - Hybridapps auf Steroiden

it('should return movies which titles contain the text lo', inject([Movies], (movieRepository) => {

var movies = movieRepository.search("lo"); var foundSearchPhrase = find(movies, function(movie) {

var missmatchFound = !includes(movie.Title, 'lo'); return missmatchFound; });

expect(movies.length).toBeGreaterThan(0); expect(foundSearchPhrase).toBeFalsy("Found at least one element which does not contain lo."); }));

Der 2. Test

Page 48: Ionic 2 - Hybridapps auf Steroiden

ionic g page Search

Die Search Page – noch ohne Suche (1)View:

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

<ion-content padding> <ion-list > <ion-item *ngFor="let movie of movies"> {{movie.Title}} </ion-item> </ion-list></ion-content>

Logik:

import { Component } from '@angular/core';import { Movies } from '../../providers/movies/movies';

@Component({ templateUrl: 'build/pages/search/search.html', providers: [Movies]})

export class SearchPage { public movies: any;

constructor(private movieRepository: Movies) { this.movieRepository.search("lo").then(data => {

this.movies = data; }); }}

Page 49: Ionic 2 - Hybridapps auf Steroiden

Die Search Page – noch ohne Suche (2)import { Component } from '@angular/core';import { ionicBootstrap, Platform } from 'ionic-angular';import { StatusBar } from 'ionic-native';import { SearchPage } from './pages/Search/Search';

@Component({ template: '<ion-nav [root]="rootPage"></ion-nav>‚})

export class MyApp { rootPage: any = SearchPage;

constructor(public platform: Platform) {platform.ready().then(() => {

StatusBar.styleDefault(); }); }}

ionicBootstrap(MyApp);

app.ts anpassen

Page 50: Ionic 2 - Hybridapps auf Steroiden

Die Search Page – noch ohne Suche (3)ionic serve

Page 51: Ionic 2 - Hybridapps auf Steroiden

Die Search Page – mit On-Input Suche<ion-header> …</ion-header>

<ion-content padding> <ion-searchbar name="searchBar"

[(ngModel)]="searchText" (ionInput)="onSearchInput($event)" >

<!-- [showCancelButton]="shouldShowCancel" (ionCancel)="onCancel($event)"> --> </ion-searchbar>

<ion-list > <ion-item *ngFor="let movie of movies"> {{movie.Title}} </ion-item> </ion-list>

</ion-content>

export class SearchPage { public movies: any; public searchText: string;

public onSearchInput() { this.search(this.searchText);

}

constructor(private movieRepository: Movies) { }

private search(text: string){ this.movieRepository.search(text)

.then(data => this.movies = data) .catch(error => console.log(error));

}}

Page 52: Ionic 2 - Hybridapps auf Steroiden

Binding Typen<ion-header> …</ion-header>

<ion-content padding> <ion-searchbar name="searchBar"

[(ngModel)]="searchText" [showCancelButton]="shouldShowCancel"

(ionInput)="onSearchInput($event)" (ionCancel)="onCancel($event)"> </ion-searchbar>

<ion-list > <ion-item *ngFor="let movie of movies"> {{movie.Title}} </ion-item> </ion-list>

</ion-content>

One Way Binding

Interpolation

Event Binding

One Way Binding

Page 53: Ionic 2 - Hybridapps auf Steroiden

Die Search Page mit Thumbnails<ion-content padding>…

<ion-list> <ion-item *ngFor="let movie of movies"> <ion-thumbnail item-left> <img *ngIf="movie.Poster !== 'N/A'" src="{{movie.Poster}}"> </ion-thumbnail>

<h2>{{movie.Title}}</h2> <p>{{movie.Year}}</p> <p>{{movie.Type}}</p>

</ion-item> </ion-list></ion-content>

Page 54: Ionic 2 - Hybridapps auf Steroiden

Die Search Page mit Thumbnails und Sliding<ion-content padding>…

<ion-list> <ion-item-sliding *ngFor="let movie of movies"> <ion-item> … </ion-item>

<ion-item-options side="right"><button primary>

<ion-icon ios="ios-star" md="md-star"></ion-icon></button>

</ion-item-options > </ion-item-sliding> </ion-list></ion-content>

Page 55: Ionic 2 - Hybridapps auf Steroiden

Die DetailansichtTop Down entwickeln

Search Favorites About

Details

Tabs

Input

Page 56: Ionic 2 - Hybridapps auf Steroiden

ionic g page Details

Die Details Page Styling (1)Logik:import { Component } from '@angular/core';

@Component({ templateUrl: 'build/pages/details/details.html',})export class DetailsPage {

public movie: any;

constructor() { this.movie = { "Title": "Lo", "Year": "2009", "Rated": "N/A", "Released": "24 Oct 2009", "Runtime": "80 min",

… } }}

App.ts

export class MyApp { rootPage: any = DetailsPage;

constructor(public platform: Platform) { platform.ready().then(() => {

StatusBar.styleDefault(); }); }}

Page 57: Ionic 2 - Hybridapps auf Steroiden

Die Details Page Styling (2)<ion-content padding> <ion-card> <h2>{{movie.Title}}</h2> <p>{{movie.Year}}</p> <img *ngIf="movie.Poster !== 'N/A'" src="{{movie.Poster}}"> <ion-card-content> <p>{{movie.Plot}}</p> </ion-card-content> <ion-row> <ion-col> <ion-badge>

<ion-icon name="star-half">{{movie.imdbRating}}</ion-icon></ion-badge>

</ion-col> <ion-col> <ion-badge>

<ion-icon name="text"> {{movie.imdbVotes}}</ion-icon></ion-badge>

</ion-col> </ion-row> </ion-card></ion-content>

Page 58: Ionic 2 - Hybridapps auf Steroiden

Die Details Page Daten

Provider

public getMovie(imdbID: string) {

return new Promise(resolve => { let url = 'http://www.omdbapi.com/?i=' + imdbID; console.log('start getting movie:' + url);

this.http.get(url) .map(result => result.json()) .subscribe(data => resolve(data)); }); }

Logik

import { Component } from '@angular/core';import { Movies } from '../../providers/movies/movies';

@Component({ templateUrl: 'build/pages/details/details.html', providers: [Movies]})export class DetailsPage {

public movie: any = {};

constructor(private movieRepository: Movies) { this.setMovie("tt1047490"); }

private setMovie(imdbId: string){ this.movieRepository.getMovie(imdbId) .then(data => this.movie = data ); }}

Page 59: Ionic 2 - Hybridapps auf Steroiden

Die Details Page Daten mit OnInit import { Component, OnInit } from '@angular/core';import { Movies } from '../../providers/movies/movies';

@Component({ templateUrl: 'build/pages/details/details.html', providers: [Movies]})

export class DetailsPage implements OnInit {

public movie: any = {};

constructor(private movieRepository: Movies) { }

ngOnInit() { this.setMovie("tt1047490"); }

private setMovie(imdbId: string){ … }}

Quelle: https://angular.io/docs/ts/latest/guide/lifecycle-hooks.html

Page 60: Ionic 2 - Hybridapps auf Steroiden

Die Navigation per Navigation Controller

Search Favorites About

Details

Tabs

Input

Page 61: Ionic 2 - Hybridapps auf Steroiden

Navigation & Parameterübergabe programmatischView… <ion-list> <ion-item-sliding *ngFor="let movie of movies"> <button ion-item (click)="showDetails(movie.imdbID)"> <ion-thumbnail item-left> <img *ngIf="movie.Poster !== 'N/A'" src="{{movie.Poster}}"> </ion-thumbnail> <h2>{{movie.Title}}</h2> <p>{{movie.Year}}</p> <p>{{movie.Type}}</p> </button>

<ion-item-options side="right"> <button primary> <ion-icon ios="ios-star" md="md-star"></ion-icon> </button> </ion-item-options> </ion-item-sliding> </ion-list>…

Logik…import { NavController } from 'ionic-angular';import { DetailsPage } from '../details/details';

@Component({ templateUrl: 'build/pages/search/search.html', providers: [Movies]})export class SearchPage {

public showDetails(imdbID: string) { this.navCtrl.push(DetailsPage, {"id": imdbID); }

constructor(private movieRepository: Movies, public navCtrl: NavController) {

}

Page 62: Ionic 2 - Hybridapps auf Steroiden

Ergebnis der Anpassung der Suche

Page 63: Ionic 2 - Hybridapps auf Steroiden

Navigation & Parameterübergabe deklarativ

<button ion-item [navPush]="detailsPage" [navParams]="movie" > <ion-thumbnail item-left> <img *ngIf="movie.Poster !== 'N/A'" src="{{movie.Poster}}"> </ion-thumbnail> <h2>{{movie.Title}}</h2> <p>{{movie.Year}}</p> <p>{{movie.Type}}</p> </button>

Page 64: Ionic 2 - Hybridapps auf Steroiden

Navigationsparameter abrufenimport { Component, OnInit } from '@angular/core';import { Movies } from '../../providers/movies/movies';import { NavParams } from 'ionic-angular';

@Component({ templateUrl: 'build/pages/details/details.html', providers: [Movies]})export class DetailsPage implements OnInit{

public movie: any = {};

constructor(private movieRepository: Movies, private params: NavParams) { }

ngOnInit() { this.setMovie(this.params.get("id")); }…

Page 65: Ionic 2 - Hybridapps auf Steroiden

Zurück navigierenLogik…import { NavController } from 'ionic-angular';

@Component({ templateUrl: 'build/pages/search/search.html', providers: [Movies]})export class SearchPage {

public goBack() { this.navCtrl.pop(); }

constructor(private movieRepository: Movies, public navCtrl: NavController) {

}

<ion-navbar>…</ion-navbar>

Page 66: Ionic 2 - Hybridapps auf Steroiden

Navigation ohne Stackimport { App, ViewChild } from '@angular/core';import { NavController } from 'ionic-angular';

@App({ template: '<ion-nav #myNav [root]="rootPage"></ion-nav>'})export class MyApp { @ViewChild('myNav') nav: NavController private rootPage = TabsPage;

// Wait for the components in MyApp's template to be initialized // In this case, we are waiting for the Nav with id="my-nav" ngAfterViewInit() { // Let's navigate from TabsPage to Page1 this.nav.push(Page1); }}

Page 67: Ionic 2 - Hybridapps auf Steroiden

Favorites Pageionic g page Favorites

<ion-header>

<ion-navbar> <ion-title>Favorites</ion-title> </ion-navbar>

</ion-header>

<ion-content padding> Hier finden sich irgend wann einmal die beliebtesten Filme des Nutzers.</ion-content>

Page 68: Ionic 2 - Hybridapps auf Steroiden

Die Tabs

Search Favorites About

Details

Tabs

Input

Page 69: Ionic 2 - Hybridapps auf Steroiden

About Pageionic g page About

<ion-header>

<ion-navbar> <ion-title>About</ion-title> </ion-navbar>

</ion-header>

<ion-content padding> <p>Diese App wurde von Hendrik Lösch gebaut...</p> <p> Alle Quellen finden sich <a href="https://github.com/HerrLoesch/MoviewMania">hier</a></p>

</ion-content>

Page 70: Ionic 2 - Hybridapps auf Steroiden

Die Tabs

App.html<ion-tabs selectedIndex="1"> <ion-tab tabTitle="Search" tabIcon="search" [root]="searchRoot"></ion-tab> <ion-tab tabTitle="Favorites" tabIcon="star" [root]="favoritesRoot" tabBadge="5" tabBadgeStyle="danger"></ion-tab> <ion-tab tabTitle="About" tabIcon="information" [root]="aboutRoot"></ion-tab></ion-tabs>

Page 71: Ionic 2 - Hybridapps auf Steroiden

Anpassung der App.tsApp.tsimport { SearchPage } from './pages/Search/Search';import { FavoritesPage } from './pages/favorites/favorites';import { AboutPage } from './pages/about/about';

@Component({ templateUrl: 'build/app.html'})export class MyApp {

searchRoot = SearchPage; favoritesRoot = FavoritesPage; aboutRoot = AboutPage;

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

ionicBootstrap(MyApp);

Page 72: Ionic 2 - Hybridapps auf Steroiden

Modals

Search Favorites About

Details

Tabs

Input

Page 73: Ionic 2 - Hybridapps auf Steroiden
Page 74: Ionic 2 - Hybridapps auf Steroiden

Anpassungen an der SucheView:

<ion-item-options side="right"> <button primary (click)="addFavorite(movie)"> <ion-icon ios="ios-star" md="md-star"></ion-icon> </button> </ion-item-options>

Logik:import { NavController, ModalController } from 'ionic-angular';import { FavoriteInput } from '../favorite-input/favorite-input';

@Component({ templateUrl: 'search.html', providers: [Movies]})export class SearchPage { constructor(... private modalCtrl: ModalController) { }

public addFavorite(movie: any){ console.log("start adding favorite:"); console.log(movie);

let modal = this.modalCtrl.create(FavoriteInput, movie); modal.present(); }…

Page 75: Ionic 2 - Hybridapps auf Steroiden

Die Eingabemaske<ion-header> <ion-toolbar> <ion-title> Add Favorite </ion-title> <ion-buttons start> <button ion-button (click)="dismiss()"> <span color="primary" showWhen="ios">Cancel</span> <ion-icon name="md-close" showWhen="android,windows"></ion-icon> </button> </ion-buttons> </ion-toolbar></ion-header>

<ion-content padding> <h2>{{title}}</h2> <p>{{year}}</p>

<ion-item> <ion-textarea placeholder="comments" rows="5"></ion-textarea> </ion-item>

<button (click)="save()" ion-button full>Save</button></ion-content>

Page 76: Ionic 2 - Hybridapps auf Steroiden

Die Logikimport { Component, OnInit } from '@angular/core';import { NavParams, ViewController } from 'ionic-angular';

@Component({ selector: 'page-favorite-input', templateUrl: 'favorite-input.html'})export class FavoriteInput implements OnInit {

title:string; year:string;

ngOnInit() { this.title = this.params.get("Title"); this.year = this.params.get("Year"); }

constructor(private params: NavParams, private viewController: ViewController) {}

public dismiss() { this.viewController.dismiss(); }

public save(){ }}

Geht nicht für komplexe Datentypen

Page 77: Ionic 2 - Hybridapps auf Steroiden

Forms mit FormBuilder

Search Favorites About

Details

Tabs

Input

?

Page 78: Ionic 2 - Hybridapps auf Steroiden

View:<form (ngSubmit)="save()" [formGroup]="formData"> <ion-item> <ion-textarea placeholder="comments"rows="5" formControlName="comments"></ion-textarea> </ion-item>

<button type="submit" [disabled]="!formData.valid" ion-button full>Save</button></form>

Anpassungen an Favorite InputLogik:import {Validators, FormBuilder, FormGroup } from '@angular/forms';...export class FavoriteInput implements OnInit {

formData: FormGroup;

constructor(... private formBuilder: FormBuilder) {

this.formData = this.formBuilder.group({comments: ['', Validators.minLength(5)]});

}

public save(){ let favorite = { "comments": this.formData.value.comments, "imdbID": this.params.get("imdbID") };

this.viewController.dismiss(); }

Page 79: Ionic 2 - Hybridapps auf Steroiden

Native Storage & PluginsWhy?This plugin is created because of the non-persistent property of LocalStorage in the WebView of Android and iOS. In iOS stored data from LocalStorage can be removed by the OS, when running out of memory.

When to use the plugin•Simple: Uniform and convenient way of organizing, storing, and accessing the data•Fast: Less than 1 milisecond to save or retrieve an object (in general)•Persistence: Save data over multiple sessions, i.e. holds the data till the application is removed from the device•Small data: Store small amounts of persistent data (less than a few hundred kilobytes)

• It is possible to store more than a few megabytes, but that's not the intended usage of the plugin.

Quelle: https://github.com/TheCocoaProject/cordova-plugin-nativestorage

Page 80: Ionic 2 - Hybridapps auf Steroiden

Plugin hinzufügennpm install –g cordova

ionic plugin add cordova-plugin-nativestorage

ionic g provider store

Nur falls Cordova noch nicht installiert ist.

Fügt es nur der config.xml aber nichtpackage.json hinzu!!!

"cordovaPlugins": [ "cordova-plugin-whitelist", "cordova-plugin-console", "cordova-plugin-statusbar", "cordova-plugin-device", "cordova-plugin-splashscreen", "ionic-plugin-keyboard", "cordova-plugin-nativestorage" ],

Page 81: Ionic 2 - Hybridapps auf Steroiden

Provider erzeugenionic g provider favoriteStore

import { Injectable, OnInit, OnDestroy } from '@angular/core';import 'rxjs/add/operator/map';import { NativeStorage } from 'ionic-native';

@Injectable()export class FavoritesStore implements OnInit, OnDestroy {

constructor(private nativeStorage: NativeStorage) { }

private dataKey: "favorites";

private favorites: Array<any>;

public ngOnInit() { this.loadFavorites(); }

public ngOnDestroy(){ this.saveFavorites(); }

private loadFavorites() { NativeStorage.getItem(this.dataKey) .then( data => this.favorites = data, error => console.error(error) ); }

private saveFavorites() { NativeStorage.setItem(this.dataKey, {property: this.favorites}) .then( () => { console.log('Stored favorites'); console.log(this.favorites); }, error => console.error('Error storing item', error) ); }

public addFavorite(favorite: any) { this.favorites.push(favorite); }

public getFavorites(){ return this.favorites; }}

Page 82: Ionic 2 - Hybridapps auf Steroiden

Provider bereitstellenapp.module.ts

import { FavoritesStore } from '../providers/favoritesStore';import { NativeStorage } from 'ionic-native';

@NgModule({ declarations: [… ], imports: [ IonicModule.forRoot(MyApp) ], bootstrap: [IonicApp], entryComponents: [… ], providers: [FavoritesStore, NativeStorage]})

Dadurch steht die gleiche Instanz des Providers allen zur Verfügung.

Page 83: Ionic 2 - Hybridapps auf Steroiden

Provider Nutzenimport { FavoritesStore } from '../../providers/favoritesStore';

@Component({ selector: 'page-favorite-input', templateUrl: 'favorite-input.html'})export class FavoriteInput implements OnInit {

constructor(…, private store: FavoritesStore) { }

public save(){ let favorite = { "comments": this.formData.value.comments, "imdbID": this.params.get("imdbID") };

this.store.addFavorite(favorite);

Page 84: Ionic 2 - Hybridapps auf Steroiden

Alerts

Search Favorites About

Details

Tabs

Input

Page 85: Ionic 2 - Hybridapps auf Steroiden

Anpassungen an Favorite Input let confirmation = this.alertController.create({ title: 'Add Favorite?', message: 'Do you want to add ' + this.title + ' as favorite?', buttons: [ { text: 'Disagree', handler: () => { } }, { text: 'Agree', handler: () => { this.addFavorite(); this.viewController.dismiss(); } } ] }); confirmation.present();

Page 86: Ionic 2 - Hybridapps auf Steroiden

Toasts

Search Favorites About

Details

Tabs

Input

Page 87: Ionic 2 - Hybridapps auf Steroiden

Anpassungen an Favorite Input

showScuessToast() { let toast = this.toastCtrl.create({ message: 'Favorite was added successfully', duration: 3000, position: 'top' });

toast.present(); }

Page 88: Ionic 2 - Hybridapps auf Steroiden

Die Schei#e geht net!

Page 89: Ionic 2 - Hybridapps auf Steroiden

Probleme beim Erstellen eines neuen Projekts weil npm kein install ausführen kann.

Lösung: Aller neuste Node Version installieren und den Rechner neu starten.

Page 90: Ionic 2 - Hybridapps auf Steroiden

Man kann selbst in neuen Projekten keine Ionicons sehen(betrifft vor allem RC0)

^ Symbol entfernen oder auf Version 2.0.0 wechseln

Danach noch einmal npm install ausführen.

Page 91: Ionic 2 - Hybridapps auf Steroiden

Es ist nicht möglich zu einer bestimmten Seite zu wechseln

Die Seite muss in declarations und(!) entryComponents der app.module.ts eingetragen werden.