SlideShare ist ein Scribd-Unternehmen logo
1 von 91
Ionic 2
HYBRID APPS AUF STEROIDEN
Inhalte
Projektumgebung
- 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
Szenario
Search Favorites About
Details
Tabs
Input
Installation und Vorbereitung
Webstorm (€) Visual Studio Code Visual Studio (€) Atom Chrome
http://cmder.net/
1. npm installieren: nodejs.org/en/download/
2. npm install –g cordova
3. npm install –g ionic
4. npm install –g typings
Was ist Ionic?
Die CLI
npm --version Version con NPM abrufen
npm help {befehl} Ruft die Hilfe für den entsprechenden Befehl auf
npm install [-g] {Paketname} Installiert das Paket im aktuellen Projekt bzw. global
npm 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
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
Die App bauen
Infrastruktur aufsetzen
Ionic start myApp –v2 blank
cd {app name}
ionic serve --lab
Jede Seite erhält ein Verzeichnis mit:
- Darstellung .html
- Styles .scss
- Logik .ts
Applikationsweite Einstellungen können plattformspezifisch konfiguriert werden.
Das Bootstrapping wird an zentraler Stelle verwaltet und beim Programmstart eingeleitet.
Cordova plugins werden zentral gespeichert und direkt über Ionic verwendet.
Es gibt kein ngCordova!
Cordova Plugins u.ä. werden über Hooks in die Applikation eingebunden.
Dies geschieht weitestgehend automatisch.
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!
Splash screens und App Icons können für jedes plattform gesondert
angegeben werden.
Sie werden über die CLI aus einer Vorlage heraus generiert.
Type Script 1.x benötigt Typeings um Javascript Frameworks ansprechen zu können.
Diese sind separat mit jedem Framework herunter zu laden.
Die eigentliche App wird nach einem ionic build im www Verzeichnis zur Verfügung gestellt.
Im www Verzeichnis sollte nicht entwickelt werden!!!
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
<?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!
Testinfrastruktur hinzufügen
npm install karma --save-dev
npm install -g karma-cli
karma init karma.conf.js
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:
Komponente erzeugen mit der wir die Daten auslesen:
ionic g provider Movies
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
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
Debuggen mit Chrome
npm test
F12
ts Datei wählen
Break Point setzen
F5
Augury
Externe Bibliotheken laden
Beispiel lodash
npm install -g typings
npm install lodash --save
typings install lodash –save
import {[Funktionen die verwendet werden]} from 'lodash';
Überall wo es verwendet wird
Die Suche
Test First & Bottom Up
Search Favorites About
Details
Tabs
Input
http://www.omdbapi.com/
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
Der (Fake)Provider + Domain Object
import { 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-...
},
Quelle: http://www.joshmorony.com/an-in-depth-explanation-of-providers-in-ionic-2/
Was ist ein Provider
Der echte Provider
import { 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));
});
}
}
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
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;
});
}}
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
Die Search Page – noch ohne Suche (3)
ionic serve
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));
}
}
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
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>
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>
Die Detailansicht
Top Down entwickeln
Search Favorites About
Details
Tabs
Input
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();
});
}
}
…
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>
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 );
}
}
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
Die Navigation per Navigation Controller
Search Favorites About
Details
Tabs
Input
Navigation & Parameterübergabe programmatisch
View
…
<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) {
}
…
Ergebnis der Anpassung der Suche
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>
Navigationsparameter abrufen
import { 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"));
}
…
Zurück navigieren
Logik
…
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>
Navigation ohne Stack
import { 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);
}
}
Favorites Page
ionic 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>
Die Tabs
Search Favorites About
Details
Tabs
Input
About Page
ionic 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>
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>
Anpassung der App.ts
App.ts
import { 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);
Modals
Search Favorites About
Details
Tabs
Input
Anpassungen an der Suche
View:
<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();
}
…
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>
Die Logik
import { 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
Forms mit FormBuilder
Search Favorites About
Details
Tabs
Input
?
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 Input
Logik:
import {Validators, FormBuilder, FormGroup } from '@angular/for
...
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();
}
Native Storage & Plugins
Why?
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
Plugin hinzufügen
npm 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 nicht
package.json hinzu!!!
"cordovaPlugins": [
"cordova-plugin-whitelist",
"cordova-plugin-console",
"cordova-plugin-statusbar",
"cordova-plugin-device",
"cordova-plugin-splashscreen",
"ionic-plugin-keyboard",
"cordova-plugin-nativestorage"
],
Provider erzeugen
ionic 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;
}
}
Provider bereitstellen
app.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.
Provider Nutzen
import { 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);
Alerts
Search Favorites About
Details
Tabs
Input
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();
Toasts
Search Favorites About
Details
Tabs
Input
Anpassungen an Favorite Input
showScuessToast() {
let toast = this.toastCtrl.create({
message: 'Favorite was added successfully',
duration: 3000,
position: 'top'
});
toast.present();
}
Die Schei#e geht net!
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.
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.
Es ist nicht möglich zu einer bestimmten Seite zu wechseln
Die Seite muss in declarations und(!) entryComponents der app.module.ts
eingetragen werden.

Weitere ähnliche Inhalte

Was ist angesagt?

Rhomobile
RhomobileRhomobile
RhomobileJan Ow
 
Offlinefähige Browseranwendungen: Progressive Web-Apps mit Angular 2
Offlinefähige Browseranwendungen: Progressive Web-Apps mit Angular 2Offlinefähige Browseranwendungen: Progressive Web-Apps mit Angular 2
Offlinefähige Browseranwendungen: Progressive Web-Apps mit Angular 2Manfred Steyer
 
Webentwicklung für das IPhone
Webentwicklung für das IPhoneWebentwicklung für das IPhone
Webentwicklung für das IPhonereinhardh
 
Electron.NET: Cross-Platform Desktop Software mit ASP.NET Core
Electron.NET: Cross-Platform Desktop Software mit ASP.NET CoreElectron.NET: Cross-Platform Desktop Software mit ASP.NET Core
Electron.NET: Cross-Platform Desktop Software mit ASP.NET CoreGregor Biswanger
 
Aber schnell! Top HTML5 Performance Tipps für Hybrid- und Web-Apps
Aber schnell! Top HTML5 Performance Tipps für Hybrid- und Web-AppsAber schnell! Top HTML5 Performance Tipps für Hybrid- und Web-Apps
Aber schnell! Top HTML5 Performance Tipps für Hybrid- und Web-AppsGregor Biswanger
 
Jalimo Slides Linuxtag2007
Jalimo Slides Linuxtag2007Jalimo Slides Linuxtag2007
Jalimo Slides Linuxtag2007smancke
 

Was ist angesagt? (7)

Vaadinator erweitern
Vaadinator erweiternVaadinator erweitern
Vaadinator erweitern
 
Rhomobile
RhomobileRhomobile
Rhomobile
 
Offlinefähige Browseranwendungen: Progressive Web-Apps mit Angular 2
Offlinefähige Browseranwendungen: Progressive Web-Apps mit Angular 2Offlinefähige Browseranwendungen: Progressive Web-Apps mit Angular 2
Offlinefähige Browseranwendungen: Progressive Web-Apps mit Angular 2
 
Webentwicklung für das IPhone
Webentwicklung für das IPhoneWebentwicklung für das IPhone
Webentwicklung für das IPhone
 
Electron.NET: Cross-Platform Desktop Software mit ASP.NET Core
Electron.NET: Cross-Platform Desktop Software mit ASP.NET CoreElectron.NET: Cross-Platform Desktop Software mit ASP.NET Core
Electron.NET: Cross-Platform Desktop Software mit ASP.NET Core
 
Aber schnell! Top HTML5 Performance Tipps für Hybrid- und Web-Apps
Aber schnell! Top HTML5 Performance Tipps für Hybrid- und Web-AppsAber schnell! Top HTML5 Performance Tipps für Hybrid- und Web-Apps
Aber schnell! Top HTML5 Performance Tipps für Hybrid- und Web-Apps
 
Jalimo Slides Linuxtag2007
Jalimo Slides Linuxtag2007Jalimo Slides Linuxtag2007
Jalimo Slides Linuxtag2007
 

Andere mochten auch

Crash Course in AngularJS + Ionic (Deep dive)
Crash Course in AngularJS + Ionic (Deep dive)Crash Course in AngularJS + Ionic (Deep dive)
Crash Course in AngularJS + Ionic (Deep dive)ColdFusionConference
 
Rethinking Mobile with Ionic
Rethinking Mobile with IonicRethinking Mobile with Ionic
Rethinking Mobile with IonicMike Hartington
 
Effective Communication Of Data Inspired by Stephen Few
Effective Communication Of Data Inspired by Stephen FewEffective Communication Of Data Inspired by Stephen Few
Effective Communication Of Data Inspired by Stephen FewCory Grenier
 
Ionic Framework - get up and running to build hybrid mobile apps
Ionic Framework - get up and running to build hybrid mobile appsIonic Framework - get up and running to build hybrid mobile apps
Ionic Framework - get up and running to build hybrid mobile appsAndreas Sahle
 
Cordova, Angularjs & Ionic @ Codeaholics
Cordova, Angularjs & Ionic @ CodeaholicsCordova, Angularjs & Ionic @ Codeaholics
Cordova, Angularjs & Ionic @ CodeaholicsEddie Lau
 
Hybrid app in ionic framework overview
Hybrid app in ionic framework overviewHybrid app in ionic framework overview
Hybrid app in ionic framework overviewSanket Devlekar
 
Art and Science of Dashboard Design
Art and Science of Dashboard DesignArt and Science of Dashboard Design
Art and Science of Dashboard DesignSavvyData
 
Desenvolvendo uma aplicação híbrida para Android e IOs utilizando Ionic, aces...
Desenvolvendo uma aplicação híbrida para Android e IOs utilizando Ionic, aces...Desenvolvendo uma aplicação híbrida para Android e IOs utilizando Ionic, aces...
Desenvolvendo uma aplicação híbrida para Android e IOs utilizando Ionic, aces...Juliano Martins
 
Hybrid Apps with Ionic Framework
Hybrid Apps with Ionic FrameworkHybrid Apps with Ionic Framework
Hybrid Apps with Ionic FrameworkBramus Van Damme
 
Building mobile app with Ionic Framework
Building mobile app with Ionic FrameworkBuilding mobile app with Ionic Framework
Building mobile app with Ionic FrameworkHuy Trần
 
Cross Platform Mobile Apps with the Ionic Framework
Cross Platform Mobile Apps with the Ionic FrameworkCross Platform Mobile Apps with the Ionic Framework
Cross Platform Mobile Apps with the Ionic FrameworkTroy Miles
 
Ionic - Revolutionizing Hybrid Mobile Application Development
Ionic - Revolutionizing Hybrid Mobile Application DevelopmentIonic - Revolutionizing Hybrid Mobile Application Development
Ionic - Revolutionizing Hybrid Mobile Application DevelopmentJustin James
 
Cordova + Ionic + MobileFirst
Cordova + Ionic + MobileFirstCordova + Ionic + MobileFirst
Cordova + Ionic + MobileFirstRaymond Camden
 
Workshop on Hybrid App Development with Ionic Framework
Workshop on Hybrid App Development with Ionic FrameworkWorkshop on Hybrid App Development with Ionic Framework
Workshop on Hybrid App Development with Ionic FrameworkAayush Shrestha
 
Ionic Crash Course! Hack-a-ton SF
Ionic Crash Course! Hack-a-ton SFIonic Crash Course! Hack-a-ton SF
Ionic Crash Course! Hack-a-ton SFLukas Ruebbelke
 
Intro to Ionic for Building Hybrid Mobile Applications
Intro to Ionic for Building Hybrid Mobile ApplicationsIntro to Ionic for Building Hybrid Mobile Applications
Intro to Ionic for Building Hybrid Mobile ApplicationsSasha dos Santos
 
Building Mobile Applications with Ionic
Building Mobile Applications with IonicBuilding Mobile Applications with Ionic
Building Mobile Applications with IonicMorris Singer
 
Scaling Teams, Processes and Architectures
Scaling Teams, Processes and ArchitecturesScaling Teams, Processes and Architectures
Scaling Teams, Processes and ArchitecturesLorenzo Alberton
 

Andere mochten auch (20)

Crash Course in AngularJS + Ionic (Deep dive)
Crash Course in AngularJS + Ionic (Deep dive)Crash Course in AngularJS + Ionic (Deep dive)
Crash Course in AngularJS + Ionic (Deep dive)
 
Rethinking Mobile with Ionic
Rethinking Mobile with IonicRethinking Mobile with Ionic
Rethinking Mobile with Ionic
 
Effective Communication Of Data Inspired by Stephen Few
Effective Communication Of Data Inspired by Stephen FewEffective Communication Of Data Inspired by Stephen Few
Effective Communication Of Data Inspired by Stephen Few
 
Ionic Framework - get up and running to build hybrid mobile apps
Ionic Framework - get up and running to build hybrid mobile appsIonic Framework - get up and running to build hybrid mobile apps
Ionic Framework - get up and running to build hybrid mobile apps
 
Cordova, Angularjs & Ionic @ Codeaholics
Cordova, Angularjs & Ionic @ CodeaholicsCordova, Angularjs & Ionic @ Codeaholics
Cordova, Angularjs & Ionic @ Codeaholics
 
Workshop Ionic Framework - CC FE & UX
Workshop Ionic Framework - CC FE & UXWorkshop Ionic Framework - CC FE & UX
Workshop Ionic Framework - CC FE & UX
 
Hybrid app in ionic framework overview
Hybrid app in ionic framework overviewHybrid app in ionic framework overview
Hybrid app in ionic framework overview
 
Art and Science of Dashboard Design
Art and Science of Dashboard DesignArt and Science of Dashboard Design
Art and Science of Dashboard Design
 
Desenvolvendo uma aplicação híbrida para Android e IOs utilizando Ionic, aces...
Desenvolvendo uma aplicação híbrida para Android e IOs utilizando Ionic, aces...Desenvolvendo uma aplicação híbrida para Android e IOs utilizando Ionic, aces...
Desenvolvendo uma aplicação híbrida para Android e IOs utilizando Ionic, aces...
 
Hybrid Apps with Ionic Framework
Hybrid Apps with Ionic FrameworkHybrid Apps with Ionic Framework
Hybrid Apps with Ionic Framework
 
Building mobile app with Ionic Framework
Building mobile app with Ionic FrameworkBuilding mobile app with Ionic Framework
Building mobile app with Ionic Framework
 
Cross Platform Mobile Apps with the Ionic Framework
Cross Platform Mobile Apps with the Ionic FrameworkCross Platform Mobile Apps with the Ionic Framework
Cross Platform Mobile Apps with the Ionic Framework
 
Ionic - Revolutionizing Hybrid Mobile Application Development
Ionic - Revolutionizing Hybrid Mobile Application DevelopmentIonic - Revolutionizing Hybrid Mobile Application Development
Ionic - Revolutionizing Hybrid Mobile Application Development
 
Cordova + Ionic + MobileFirst
Cordova + Ionic + MobileFirstCordova + Ionic + MobileFirst
Cordova + Ionic + MobileFirst
 
Workshop on Hybrid App Development with Ionic Framework
Workshop on Hybrid App Development with Ionic FrameworkWorkshop on Hybrid App Development with Ionic Framework
Workshop on Hybrid App Development with Ionic Framework
 
Hybrid app development with ionic
Hybrid app development with ionicHybrid app development with ionic
Hybrid app development with ionic
 
Ionic Crash Course! Hack-a-ton SF
Ionic Crash Course! Hack-a-ton SFIonic Crash Course! Hack-a-ton SF
Ionic Crash Course! Hack-a-ton SF
 
Intro to Ionic for Building Hybrid Mobile Applications
Intro to Ionic for Building Hybrid Mobile ApplicationsIntro to Ionic for Building Hybrid Mobile Applications
Intro to Ionic for Building Hybrid Mobile Applications
 
Building Mobile Applications with Ionic
Building Mobile Applications with IonicBuilding Mobile Applications with Ionic
Building Mobile Applications with Ionic
 
Scaling Teams, Processes and Architectures
Scaling Teams, Processes and ArchitecturesScaling Teams, Processes and Architectures
Scaling Teams, Processes and Architectures
 

Ähnlich wie Ionic 2 - Hybridapps auf Steroiden

Augmented Reality Workshop
Augmented Reality WorkshopAugmented Reality Workshop
Augmented Reality Workshopargency
 
Entwicklungsprozess und Arbeit mit Symfony2 in der fotocommunity GmbH
Entwicklungsprozess und Arbeit mit Symfony2 in der fotocommunity GmbHEntwicklungsprozess und Arbeit mit Symfony2 in der fotocommunity GmbH
Entwicklungsprozess und Arbeit mit Symfony2 in der fotocommunity GmbHstijink
 
elemente websolutions - Zusammenfassung T3DD09
elemente websolutions - Zusammenfassung T3DD09elemente websolutions - Zusammenfassung T3DD09
elemente websolutions - Zusammenfassung T3DD09elemente websolutions
 
DWX 2017 - Alternativen zu Visual-Studio-Testtools: Wann lohnt es sich auch m...
DWX 2017 - Alternativen zu Visual-Studio-Testtools: Wann lohnt es sich auch m...DWX 2017 - Alternativen zu Visual-Studio-Testtools: Wann lohnt es sich auch m...
DWX 2017 - Alternativen zu Visual-Studio-Testtools: Wann lohnt es sich auch m...Marc Müller
 
Kuck mal, Node.js! Einstieg für .NET Entwickler mit Visual Studio Code und Ty...
Kuck mal, Node.js! Einstieg für .NET Entwickler mit Visual Studio Code und Ty...Kuck mal, Node.js! Einstieg für .NET Entwickler mit Visual Studio Code und Ty...
Kuck mal, Node.js! Einstieg für .NET Entwickler mit Visual Studio Code und Ty...Gregor Biswanger
 
Desktop Containers 12: Next Generation of ZENworks Application Virtualization
Desktop Containers 12: Next Generation of ZENworks Application VirtualizationDesktop Containers 12: Next Generation of ZENworks Application Virtualization
Desktop Containers 12: Next Generation of ZENworks Application VirtualizationGWAVA
 
Oracle oem 12c_plugin_development-doag-konferenz_11_2014_print_gunther_pipperr
Oracle oem 12c_plugin_development-doag-konferenz_11_2014_print_gunther_pipperrOracle oem 12c_plugin_development-doag-konferenz_11_2014_print_gunther_pipperr
Oracle oem 12c_plugin_development-doag-konferenz_11_2014_print_gunther_pipperrGunther Pippèrr
 
Das dreckige Dutzend - ADF Migration nach 12c in der IKB - DOAG 2014.
Das dreckige Dutzend - ADF Migration nach 12c in der IKB - DOAG 2014.Das dreckige Dutzend - ADF Migration nach 12c in der IKB - DOAG 2014.
Das dreckige Dutzend - ADF Migration nach 12c in der IKB - DOAG 2014.Torsten Kleiber
 
Composer und TYPO3
Composer und TYPO3Composer und TYPO3
Composer und TYPO3Peter Kraume
 
Hands-on Workshop: API-Dokumentation mit OpenAPI / Swagger in ASP.NET Core
Hands-on Workshop: API-Dokumentation mit OpenAPI / Swagger in ASP.NET CoreHands-on Workshop: API-Dokumentation mit OpenAPI / Swagger in ASP.NET Core
Hands-on Workshop: API-Dokumentation mit OpenAPI / Swagger in ASP.NET CoreGregor Biswanger
 
C / C++ Api for Beginners
C / C++ Api for BeginnersC / C++ Api for Beginners
C / C++ Api for BeginnersUlrich Krause
 
German: Softwareprodukte aus einem Source Code mit Javascript
German: Softwareprodukte aus einem Source Code mit JavascriptGerman: Softwareprodukte aus einem Source Code mit Javascript
German: Softwareprodukte aus einem Source Code mit JavascriptRalf Schwoebel
 
Automatischer Build mit Maven - OPITZ CONSULTING - Stefan Scheidt
Automatischer Build mit Maven - OPITZ CONSULTING - Stefan ScheidtAutomatischer Build mit Maven - OPITZ CONSULTING - Stefan Scheidt
Automatischer Build mit Maven - OPITZ CONSULTING - Stefan ScheidtOPITZ CONSULTING Deutschland
 
Abläufe mit PHP und Phing automatisieren
Abläufe mit PHP und Phing automatisierenAbläufe mit PHP und Phing automatisieren
Abläufe mit PHP und Phing automatisierenChristian Münch
 
Automatisierung von Windows-Anwendungen
Automatisierung von Windows-AnwendungenAutomatisierung von Windows-Anwendungen
Automatisierung von Windows-AnwendungenAndreas Schreiber
 
Windows 8 für Entwickler
Windows 8 für EntwicklerWindows 8 für Entwickler
Windows 8 für EntwicklerJan Hentschel
 
Gradle - Beginner's Workshop (german)
Gradle - Beginner's Workshop (german)Gradle - Beginner's Workshop (german)
Gradle - Beginner's Workshop (german)Joachim Baumann
 

Ähnlich wie Ionic 2 - Hybridapps auf Steroiden (20)

Augmented Reality Workshop
Augmented Reality WorkshopAugmented Reality Workshop
Augmented Reality Workshop
 
Fehleranalyse in SCCM
Fehleranalyse in SCCMFehleranalyse in SCCM
Fehleranalyse in SCCM
 
Entwicklungsprozess und Arbeit mit Symfony2 in der fotocommunity GmbH
Entwicklungsprozess und Arbeit mit Symfony2 in der fotocommunity GmbHEntwicklungsprozess und Arbeit mit Symfony2 in der fotocommunity GmbH
Entwicklungsprozess und Arbeit mit Symfony2 in der fotocommunity GmbH
 
elemente websolutions - Zusammenfassung T3DD09
elemente websolutions - Zusammenfassung T3DD09elemente websolutions - Zusammenfassung T3DD09
elemente websolutions - Zusammenfassung T3DD09
 
DWX 2017 - Alternativen zu Visual-Studio-Testtools: Wann lohnt es sich auch m...
DWX 2017 - Alternativen zu Visual-Studio-Testtools: Wann lohnt es sich auch m...DWX 2017 - Alternativen zu Visual-Studio-Testtools: Wann lohnt es sich auch m...
DWX 2017 - Alternativen zu Visual-Studio-Testtools: Wann lohnt es sich auch m...
 
Kuck mal, Node.js! Einstieg für .NET Entwickler mit Visual Studio Code und Ty...
Kuck mal, Node.js! Einstieg für .NET Entwickler mit Visual Studio Code und Ty...Kuck mal, Node.js! Einstieg für .NET Entwickler mit Visual Studio Code und Ty...
Kuck mal, Node.js! Einstieg für .NET Entwickler mit Visual Studio Code und Ty...
 
Desktop Containers 12: Next Generation of ZENworks Application Virtualization
Desktop Containers 12: Next Generation of ZENworks Application VirtualizationDesktop Containers 12: Next Generation of ZENworks Application Virtualization
Desktop Containers 12: Next Generation of ZENworks Application Virtualization
 
Oracle oem 12c_plugin_development-doag-konferenz_11_2014_print_gunther_pipperr
Oracle oem 12c_plugin_development-doag-konferenz_11_2014_print_gunther_pipperrOracle oem 12c_plugin_development-doag-konferenz_11_2014_print_gunther_pipperr
Oracle oem 12c_plugin_development-doag-konferenz_11_2014_print_gunther_pipperr
 
Das dreckige Dutzend - ADF Migration nach 12c in der IKB - DOAG 2014.
Das dreckige Dutzend - ADF Migration nach 12c in der IKB - DOAG 2014.Das dreckige Dutzend - ADF Migration nach 12c in der IKB - DOAG 2014.
Das dreckige Dutzend - ADF Migration nach 12c in der IKB - DOAG 2014.
 
Composer und TYPO3
Composer und TYPO3Composer und TYPO3
Composer und TYPO3
 
Hands-on Workshop: API-Dokumentation mit OpenAPI / Swagger in ASP.NET Core
Hands-on Workshop: API-Dokumentation mit OpenAPI / Swagger in ASP.NET CoreHands-on Workshop: API-Dokumentation mit OpenAPI / Swagger in ASP.NET Core
Hands-on Workshop: API-Dokumentation mit OpenAPI / Swagger in ASP.NET Core
 
C / C++ Api for Beginners
C / C++ Api for BeginnersC / C++ Api for Beginners
C / C++ Api for Beginners
 
German: Softwareprodukte aus einem Source Code mit Javascript
German: Softwareprodukte aus einem Source Code mit JavascriptGerman: Softwareprodukte aus einem Source Code mit Javascript
German: Softwareprodukte aus einem Source Code mit Javascript
 
Automatischer Build mit Maven - OPITZ CONSULTING - Stefan Scheidt
Automatischer Build mit Maven - OPITZ CONSULTING - Stefan ScheidtAutomatischer Build mit Maven - OPITZ CONSULTING - Stefan Scheidt
Automatischer Build mit Maven - OPITZ CONSULTING - Stefan Scheidt
 
Abläufe mit PHP und Phing automatisieren
Abläufe mit PHP und Phing automatisierenAbläufe mit PHP und Phing automatisieren
Abläufe mit PHP und Phing automatisieren
 
Automatisierung von Windows-Anwendungen
Automatisierung von Windows-AnwendungenAutomatisierung von Windows-Anwendungen
Automatisierung von Windows-Anwendungen
 
Windows 8 für Entwickler
Windows 8 für EntwicklerWindows 8 für Entwickler
Windows 8 für Entwickler
 
Gradle - Beginner's Workshop (german)
Gradle - Beginner's Workshop (german)Gradle - Beginner's Workshop (german)
Gradle - Beginner's Workshop (german)
 
Node.js
Node.jsNode.js
Node.js
 
Einführung in Docker
Einführung in DockerEinführung in Docker
Einführung in Docker
 

Mehr von Hendrik Lösch

Why (most) softwareprojects fail silently
Why (most) softwareprojects fail silentlyWhy (most) softwareprojects fail silently
Why (most) softwareprojects fail silentlyHendrik Lösch
 
We (don't) need a software architect!?!
We (don't) need a software architect!?!We (don't) need a software architect!?!
We (don't) need a software architect!?!Hendrik Lösch
 
Restrukturierung einer industriellen Großapplikation
Restrukturierung einer industriellen GroßapplikationRestrukturierung einer industriellen Großapplikation
Restrukturierung einer industriellen GroßapplikationHendrik Lösch
 
Vom Monolith zum Modulith
Vom Monolith zum ModulithVom Monolith zum Modulith
Vom Monolith zum ModulithHendrik Lösch
 
Der Software auf den Zahn gefühlt - Einstieg in die Architekturbewertung
Der Software auf den Zahn gefühlt - Einstieg in die ArchitekturbewertungDer Software auf den Zahn gefühlt - Einstieg in die Architekturbewertung
Der Software auf den Zahn gefühlt - Einstieg in die ArchitekturbewertungHendrik Lösch
 
„Wie reden Sie denn mit mir?!?“ – Stakeholder überzeugen als Softwarearchitekt
„Wie reden Sie denn mit mir?!?“ – Stakeholder überzeugen als Softwarearchitekt„Wie reden Sie denn mit mir?!?“ – Stakeholder überzeugen als Softwarearchitekt
„Wie reden Sie denn mit mir?!?“ – Stakeholder überzeugen als SoftwarearchitektHendrik Lösch
 
Software ist was du draus machst!
Software ist was du draus machst!Software ist was du draus machst!
Software ist was du draus machst!Hendrik Lösch
 
Einstieg in das Vueniverse
Einstieg in das VueniverseEinstieg in das Vueniverse
Einstieg in das VueniverseHendrik Lösch
 
Survivalkit für Codehausmeister
Survivalkit für CodehausmeisterSurvivalkit für Codehausmeister
Survivalkit für CodehausmeisterHendrik Lösch
 
Confessions of a Codehausmeister
Confessions of a CodehausmeisterConfessions of a Codehausmeister
Confessions of a CodehausmeisterHendrik Lösch
 
WPF Dos n Don'ts - der WPF Rundumschlag
WPF Dos n Don'ts - der WPF RundumschlagWPF Dos n Don'ts - der WPF Rundumschlag
WPF Dos n Don'ts - der WPF RundumschlagHendrik Lösch
 
Clean mit visual studio
Clean mit visual studioClean mit visual studio
Clean mit visual studioHendrik Lösch
 
Advanced Refactoring Patterns
Advanced Refactoring PatternsAdvanced Refactoring Patterns
Advanced Refactoring PatternsHendrik Lösch
 
Advanced Refactoring Patterns - Dev Day 2018
Advanced Refactoring Patterns - Dev Day 2018Advanced Refactoring Patterns - Dev Day 2018
Advanced Refactoring Patterns - Dev Day 2018Hendrik Lösch
 

Mehr von Hendrik Lösch (20)

Why (most) softwareprojects fail silently
Why (most) softwareprojects fail silentlyWhy (most) softwareprojects fail silently
Why (most) softwareprojects fail silently
 
We (don't) need a software architect!?!
We (don't) need a software architect!?!We (don't) need a software architect!?!
We (don't) need a software architect!?!
 
Restrukturierung einer industriellen Großapplikation
Restrukturierung einer industriellen GroßapplikationRestrukturierung einer industriellen Großapplikation
Restrukturierung einer industriellen Großapplikation
 
Vom Monolith zum Modulith
Vom Monolith zum ModulithVom Monolith zum Modulith
Vom Monolith zum Modulith
 
Der Software auf den Zahn gefühlt - Einstieg in die Architekturbewertung
Der Software auf den Zahn gefühlt - Einstieg in die ArchitekturbewertungDer Software auf den Zahn gefühlt - Einstieg in die Architekturbewertung
Der Software auf den Zahn gefühlt - Einstieg in die Architekturbewertung
 
„Wie reden Sie denn mit mir?!?“ – Stakeholder überzeugen als Softwarearchitekt
„Wie reden Sie denn mit mir?!?“ – Stakeholder überzeugen als Softwarearchitekt„Wie reden Sie denn mit mir?!?“ – Stakeholder überzeugen als Softwarearchitekt
„Wie reden Sie denn mit mir?!?“ – Stakeholder überzeugen als Softwarearchitekt
 
Software ist was du draus machst!
Software ist was du draus machst!Software ist was du draus machst!
Software ist was du draus machst!
 
Modular mit .NET
Modular mit .NETModular mit .NET
Modular mit .NET
 
.NET zu .NET Core
.NET zu .NET Core.NET zu .NET Core
.NET zu .NET Core
 
Workshop Vue js
Workshop Vue jsWorkshop Vue js
Workshop Vue js
 
Migrationsstrategien
MigrationsstrategienMigrationsstrategien
Migrationsstrategien
 
Einstieg in das Vueniverse
Einstieg in das VueniverseEinstieg in das Vueniverse
Einstieg in das Vueniverse
 
Survivalkit für Codehausmeister
Survivalkit für CodehausmeisterSurvivalkit für Codehausmeister
Survivalkit für Codehausmeister
 
Confessions of a Codehausmeister
Confessions of a CodehausmeisterConfessions of a Codehausmeister
Confessions of a Codehausmeister
 
Hey, wie geht es dir?
Hey, wie geht es dir?Hey, wie geht es dir?
Hey, wie geht es dir?
 
WPF Dos n Don'ts - der WPF Rundumschlag
WPF Dos n Don'ts - der WPF RundumschlagWPF Dos n Don'ts - der WPF Rundumschlag
WPF Dos n Don'ts - der WPF Rundumschlag
 
Clean mit visual studio
Clean mit visual studioClean mit visual studio
Clean mit visual studio
 
Advanced Refactoring Patterns
Advanced Refactoring PatternsAdvanced Refactoring Patterns
Advanced Refactoring Patterns
 
Codesmells
CodesmellsCodesmells
Codesmells
 
Advanced Refactoring Patterns - Dev Day 2018
Advanced Refactoring Patterns - Dev Day 2018Advanced Refactoring Patterns - Dev Day 2018
Advanced Refactoring Patterns - Dev Day 2018
 

Ionic 2 - Hybridapps auf Steroiden

  • 1. Ionic 2 HYBRID APPS AUF STEROIDEN
  • 2.
  • 3. Inhalte Projektumgebung - 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
  • 6. Webstorm (€) Visual Studio Code Visual Studio (€) Atom Chrome
  • 8. 1. npm installieren: nodejs.org/en/download/ 2. npm install –g cordova 3. npm install –g ionic 4. npm install –g typings
  • 10.
  • 11.
  • 12.
  • 14. npm --version Version con NPM abrufen npm help {befehl} Ruft die Hilfe für den entsprechenden Befehl auf npm install [-g] {Paketname} Installiert das Paket im aktuellen Projekt bzw. global npm 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
  • 15. 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
  • 18. Ionic start myApp –v2 blank
  • 19. cd {app name} ionic serve --lab
  • 20. Jede Seite erhält ein Verzeichnis mit: - Darstellung .html - Styles .scss - Logik .ts
  • 21. Applikationsweite Einstellungen können plattformspezifisch konfiguriert werden.
  • 22. Das Bootstrapping wird an zentraler Stelle verwaltet und beim Programmstart eingeleitet.
  • 23. Cordova plugins werden zentral gespeichert und direkt über Ionic verwendet. Es gibt kein ngCordova!
  • 24. Cordova Plugins u.ä. werden über Hooks in die Applikation eingebunden. Dies geschieht weitestgehend automatisch.
  • 25. 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!
  • 26. Splash screens und App Icons können für jedes plattform gesondert angegeben werden. Sie werden über die CLI aus einer Vorlage heraus generiert.
  • 27. Type Script 1.x benötigt Typeings um Javascript Frameworks ansprechen zu können. Diese sind separat mit jedem Framework herunter zu laden.
  • 28. Die eigentliche App wird nach einem ionic build im www Verzeichnis zur Verfügung gestellt. Im www Verzeichnis sollte nicht entwickelt werden!!!
  • 29. 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
  • 30. <?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!
  • 32. npm install karma --save-dev npm install -g karma-cli karma init karma.conf.js
  • 33. 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:
  • 34. Komponente erzeugen mit der wir die Daten auslesen: ionic g provider Movies
  • 35. 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
  • 36. 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
  • 37. Debuggen mit Chrome npm test F12 ts Datei wählen Break Point setzen F5
  • 40. Beispiel lodash npm install -g typings npm install lodash --save typings install lodash –save import {[Funktionen die verwendet werden]} from 'lodash'; Überall wo es verwendet wird
  • 41. Die Suche Test First & Bottom Up Search Favorites About Details Tabs Input
  • 43. 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
  • 44. Der (Fake)Provider + Domain Object import { 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-... },
  • 46. Der echte Provider import { 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)); }); } }
  • 47. 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
  • 48. 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; }); }}
  • 49. 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
  • 50. Die Search Page – noch ohne Suche (3) ionic serve
  • 51. 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)); } }
  • 52. 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
  • 53. 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>
  • 54. 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>
  • 55. Die Detailansicht Top Down entwickeln Search Favorites About Details Tabs Input
  • 56. 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(); }); } } …
  • 57. 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>
  • 58. 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 ); } }
  • 59. 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
  • 60. Die Navigation per Navigation Controller Search Favorites About Details Tabs Input
  • 61. Navigation & Parameterübergabe programmatisch View … <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) { } …
  • 63. 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>
  • 64. Navigationsparameter abrufen import { 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")); } …
  • 65. Zurück navigieren Logik … 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>
  • 66. Navigation ohne Stack import { 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); } }
  • 67. Favorites Page ionic 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>
  • 68. Die Tabs Search Favorites About Details Tabs Input
  • 69. About Page ionic 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>
  • 70. 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>
  • 71. Anpassung der App.ts App.ts import { 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);
  • 73.
  • 74. Anpassungen an der Suche View: <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(); } …
  • 75. 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>
  • 76. Die Logik import { 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
  • 77. Forms mit FormBuilder Search Favorites About Details Tabs Input ?
  • 78. 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 Input Logik: import {Validators, FormBuilder, FormGroup } from '@angular/for ... 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(); }
  • 79. Native Storage & Plugins Why? 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
  • 80. Plugin hinzufügen npm 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 nicht package.json hinzu!!! "cordovaPlugins": [ "cordova-plugin-whitelist", "cordova-plugin-console", "cordova-plugin-statusbar", "cordova-plugin-device", "cordova-plugin-splashscreen", "ionic-plugin-keyboard", "cordova-plugin-nativestorage" ],
  • 81. Provider erzeugen ionic 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; } }
  • 82. Provider bereitstellen app.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.
  • 83. Provider Nutzen import { 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);
  • 85. 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();
  • 87. Anpassungen an Favorite Input showScuessToast() { let toast = this.toastCtrl.create({ message: 'Favorite was added successfully', duration: 3000, position: 'top' }); toast.present(); }
  • 89. 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.
  • 90. 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.
  • 91. Es ist nicht möglich zu einer bestimmten Seite zu wechseln Die Seite muss in declarations und(!) entryComponents der app.module.ts eingetragen werden.