lecture 7 introduction to ionic 2 - jan václavíkjanvaclavik.cz/others/codecamp/7.pdf · 6 /95 /95...
TRANSCRIPT
/95
I N S TA L L I O N I C 2 & C R E AT E N E W A P P L I C AT I O N
3
$ npm install -g ionic@beta$ ionic start my-first-ionic2-app [tabs|sidemenu|blank] --v2 [--ts]
$ ionic serve
/954
$ npm install -g ionic@beta$ ionic start my-first-ionic2-app [tabs|sidemenu|blank] --v2 [--ts]
$ ionic serve
I N S TA L L I O N I C 2 & C R E AT E N E W A P P L I C AT I O N
Ionic version 2
/955
$ npm install -g ionic@beta$ ionic start my-first-ionic2-app [tabs|sidemenu|blank] --v2 [--ts]
$ ionic serve
Create TypeScript project
I N S TA L L I O N I C 2 & C R E AT E N E W A P P L I C AT I O N
Ionic version 2
/95
• Component-based model
• Angular2
• ES6 / TypeScript (transpiling)
• Windows 10 support, Android Material Design
• Generator
• Better theming & performance
• More scalable structure
W H Y I O N I C 2
6
/95
E C M A S C R I P T 6 / T Y P E S C R I P T
• Classes (OOP)
• Fat arrow (=>)
• Promises
• Components (modules)
• Block scoping
9
/95
C L A S S E S
10
• Mapping real world object into the abstract
class Shape { constructor (id, x, y) { this.id = id this.move(x, y) } move (x, y) { this.x = x this.y = y } }
/95
C L A S S E S
11
• Mapping real world object into the abstract
Constructor is called when creating instance of class
class Shape { constructor (id, x, y) { this.id = id this.move(x, y) } move (x, y) { this.x = x this.y = y } }
/95
FAT A R R O W F U N C T I O N S
13
someFunction(function(response){ console.log(response); });
Has local context
/95
FAT A R R O W F U N C T I O N S
14
someFunction(function(response){ console.log(response); });
someFunction((response) => { console.log(response); });
Has local context
/95
FAT A R R O W F U N C T I O N S
15
someFunction(function(response){ console.log(response); });
someFunction((response) => { console.log(response); });
Has local context
Has parent context
/95
P R O M I S E S
16
doSomething().then((response) => { console.log(response); });
For more details see Lecture 5
/95
I M P O R T & E X P O R T C O M P O N E N T S
17
// lib/math.js export function sum (x, y) {return x + y} export var pi = 3.141593
// someApp.js import * as math from "lib/math" console.log("2PI = " + math.sum(math.pi, math.pi))
// otherApp.js import {sum, pi} from "lib/math" console.log("2PI = " + sum(pi, pi))
/95
I M P O R T & E X P O R T C O M P O N E N T S
18
// lib/math.js export function sum (x, y) {return x + y} export var pi = 3.141593
// someApp.js import * as math from "lib/math" console.log("2PI = " + math.sum(math.pi, math.pi))
// otherApp.js import {sum, pi} from "lib/math" console.log("2PI = " + sum(pi, pi))
Specify visible functions, vars
/95
I M P O R T & E X P O R T C O M P O N E N T S
19
// lib/math.js export function sum (x, y) {return x + y} export var pi = 3.141593
// someApp.js import * as math from "lib/math" console.log("2PI = " + math.sum(math.pi, math.pi))
// otherApp.js import {sum, pi} from "lib/math" console.log("2PI = " + sum(pi, pi))
Can call functions from components
Specify visible functions, vars
/95
I M P O R T & E X P O R T C O M P O N E N T S
20
// lib/math.js export function sum (x, y) {return x + y} export var pi = 3.141593
// someApp.js import * as math from "lib/math" console.log("2PI = " + math.sum(math.pi, math.pi))
// otherApp.js import {sum, pi} from "lib/math" console.log("2PI = " + sum(pi, pi))
Can call functions from components
Specify visible functions, vars
/95
I M P O R T & E X P O R T C O M P O N E N T S I N I O N I C 2
21
import {Page} from 'ionic-angular'; import {MoviesPage} from '../movies/movies';
/95
I M P O R T & E X P O R T C O M P O N E N T S I N I O N I C 2
22
import {Page} from 'ionic-angular'; import {MoviesPage} from '../movies/movies';
Import from Ionic
/95
B L O C K S C O P I N G
23
for (let i = 0; i < movies.length; i++) { let x = movies[i]; } console.log(x);
/95
B L O C K S C O P I N G
24
for (let i = 0; i < movies.length; i++) { let x = movies[i]; } console.log(x); // Undefined
/95
T Y P E S C R I P T E X A M P L E
25
function add(x : number, y : number) : number { return x + y; } add('a', 'b');
/95
T Y P E S C R I P T E X A M P L E
26
function add(x : number, y : number) : number { return x + y; } add('a', 'b'); // Compiler error
/95
D E P E N D E N C Y I N J E C T I O N
28
import {Page, NavController, Platform} from 'ionic-angular'; @Page({ templateUrl: 'build/pages/movies/movies.html' }) export class MoviesPage { static get parameters() { return [[NavController], [Platform]]; } constructor(nav, platform) { this.nav = nav; this.platform = platform; } }
/95
D E P E N D E N C Y I N J E C T I O N
29
import {Page, NavController, Platform} from 'ionic-angular'; @Page({ templateUrl: 'build/pages/movies/movies.html' }) export class MoviesPage { static get parameters() { return [[NavController], [Platform]]; } constructor(nav, platform) { this.nav = nav; this.platform = platform; } }
Constructor is function called when new instance is created
/95
D E P E N D E N C Y I N J E C T I O N
30
import {Page, NavController, Platform} from 'ionic-angular'; @Page({ templateUrl: 'build/pages/movies/movies.html' }) export class MoviesPage { static get parameters() { return [[NavController], [Platform]]; } constructor(nav, platform) { this.nav = nav; this.platform = platform; } } Inject components
to constructorConstructor is function called when new instance is created
/95
B I N D I N G
34
<input [value]="name">
<button (click)="someFunction($event)"></button>
One-way data binding []
/95
B I N D I N G
35
<input [value]="name">
<button (click)="someFunction($event)"></button>
One-way data binding []
Call function on event ()
/95
B I N D I N G
36
<input [value]="name">
<button (click)="someFunction($event)"></button>
One-way data binding []
<input [value]="name" (input)="name = $event.target.value">
Call function on event ()
/95
B I N D I N G
37
<input [value]="name">
<button (click)="someFunction($event)"></button>
One-way data binding []
<input [value]="name" (input)="name = $event.target.value"> <!-- or --> <input [(ngModel)]="name">
Call function on event ()
/95
B I N D I N G
38
<input [value]="name">
<button (click)="someFunction($event)"></button>
One-way data binding []
Two-way data binding [()]
<input [value]="name" (input)="name = $event.target.value"> <!-- or --> <input [(ngModel)]="name">
Call function on event ()
/95
R E N D E R I N G
40
<p>Hello my name is {{name}} and I like {{thing}}.</p>
The same as in Angular1
/95
C R E AT E L O C A L VA R I A B L E
41
<p #myParagraph></p> <button (click)="myParagraph.innerHTML = 'Fill element with something...'">
/95
C R E AT E L O C A L VA R I A B L E
42
<p #myParagraph></p> <button (click)="myParagraph.innerHTML = 'Fill element with something...'">
# means variable
/95
D E C O R AT O R S
• Metadata and info about classes
• Directly above class definition
• Starts with @
43
/95
D E C O R AT O R T Y P E S
• @App – Declare class for root component in Angular2
• @Component – Separately usable element (template, style, logic)
• @Page – Ionic-specific component
• @Directive – Modify behavior of existing component
• @Injectable – Inject to constructor, for creating services
• @Pipe – similar with filter in Angular1
• …
44
/95
D E C O R AT O R E X A M P L E
45
import {Page, NavController, Platform} from ‘ionic-angular';
@Page({ templateUrl: 'build/pages/movies/movies.html' }) export class MoviesPage { ... }
/95
D E C O R AT O R E X A M P L E
46
import {Page, NavController, Platform} from ‘ionic-angular';
@Page({ templateUrl: 'build/pages/movies/movies.html' }) export class MoviesPage { ... }
Decorator for Ionic2 page
/95
D E C O R AT O R E X A M P L E
47
import {Page, NavController, Platform} from ‘ionic-angular';
@Page({ templateUrl: 'build/pages/movies/movies.html' }) export class MoviesPage { ... }
Decorator for Ionic2 page
Object with metadata, contains template URL for specific page
/95
D I R E C T I V E S
48
<section *ngIf="showSection"></section> <li *ngFor="#item of items"></li>
Modify behavior of existing component
/95
D I R E C T I V E S
49
<section *ngIf="showSection"></section> <li *ngFor="#item of items"></li>
Array/Object iterator, the same as ng-repeat from Angular1
Modify behavior of existing component
/95
D I R E C T I V E S
50
<section *ngIf="showSection"></section> <li *ngFor="#item of items"></li>
Array/Object iterator, the same as ng-repeat from Angular1
Remember #?
Modify behavior of existing component
/95
D I R E C T I V E S
51
<section *ngIf="showSection"></section> <li *ngFor="#item of items"></li>
Array/Object iterator, the same as ng-repeat from Angular1
Remember #?
Modify behavior of existing component
* Syntactic sugar for <template>
/95
T E M P L AT E E L E M E N T, *
• <template> rendered when script is running
• * is embedded template
• You can work with HTML elements like with <template>
52
/95
L O O P I N G
53
<ion-list> <ion-item *ngFor="#movie of movies" (click)="viewMovie(movie)"> <h2>{{movie.title}}</h2> <p>{{movie.rating}} / 10</p> </ion-item> </ion-list>
/95
I O N I C 2 P R O J E C T S T R U C T U R E
54
!"" app# !"" app.js# !"" pages# # !"" page1# # # !"" page1.html# # # !"" page1.js# # # $"" page1.scss# # !"" page2# # !"" page3# # $"" tabs# $"" theme# !"" app.core.scss# !"" app.ios.scss# !"" app.md.scss# !"" app.variables.scss# $"" app.wp.scss!"" config.xml!"" gulpfile.js!"" hooks!"" ionic.config.js!"" ionic.config.json!"" node_modules!"" package.json!"" platforms!"" plugins!"" resources$"" www $"" index.html
/95
I O N I C 2 P R O J E C T S T R U C T U R E
• Do not edit code in WWW directory except index.html!
• Except resources and index.html, everything in www directory is generated automatically from app directory!
55
/95
I O N I C 2 G E N E R AT O R
• We don’t need to create and include files manually!
• Use Ionic Generator, you will love it
57
$ ionic g [page|component|directive|pipe|provider|tabs] some-name
/95
C R E AT E C O M P O N E N T
58
import {Component} from 'angular2/core'; import {IONIC_DIRECTIVES} from 'ionic-angular'; @Component({ selector: 'my-component', templateUrl: 'build/components/my-component/my-component.html', directives: [IONIC_DIRECTIVES] }) export class MyComponent { constructor() { this.text = 'Hello World'; } }
$ ionic g component my-component
app/components/my-component/my-component.js
/95
C R E AT E C O M P O N E N T
59
import {Component} from 'angular2/core'; import {IONIC_DIRECTIVES} from 'ionic-angular'; @Component({ selector: 'my-component', templateUrl: 'build/components/my-component/my-component.html', directives: [IONIC_DIRECTIVES] }) export class MyComponent { constructor() { this.text = 'Hello World'; } }
Decorator for component
$ ionic g component my-component
app/components/my-component/my-component.js
/95
C R E AT E PA G E
60
$ ionic g page my-page
app/pages/my-page/my-page.js
import {Page, NavController} from 'ionic-angular'; @Page({ templateUrl: 'build/pages/my-page/my-page.html', }) export class MyPagePage { static get parameters() { return [[NavController]]; } constructor(nav) { this.nav = nav; } }
/95
C R E AT E PA G E
61
$ ionic g page my-page
app/pages/my-page/my-page.js
import {Page, NavController} from 'ionic-angular'; @Page({ templateUrl: 'build/pages/my-page/my-page.html', }) export class MyPagePage { static get parameters() { return [[NavController]]; } constructor(nav) { this.nav = nav; } }
Create bundle with JS + HTML + SASS
/95
C R E AT E D I R E C T I V E
62
$ ionic g directive my-super-directive
import {Directive} from 'angular2/core'; @Directive({ selector: '[my-super-directive]' // Attribute selector }) export class MySuperDirective { constructor() { console.log('Hello World'); } }
app/components/my-super-directive/my-super-directive.js
/95
C R E AT E P I P E
63
$ ionic g pipe my-old-pipes
app/pipes/my-old-pipes.js
import {Injectable, Pipe} from 'angular2/core'; @Pipe({ name: 'my-old-pipes' }) @Injectable() export class MyOldPipes { transform(value, args) { value = value + ''; // make sure it's a string return value.toLowerCase(); } }
/95
C R E AT E P R O V I D E R
64
$ ionic g provider my-provider
app/providers/my-provider/my-provider.js
import {Injectable} from 'angular2/core'; import {Http} from 'angular2/http'; import 'rxjs/add/operator/map'; @Injectable() export class MyProvider { static get parameters(){ return [[Http]] } constructor(http) { this.http = http; this.data = null; } load() { if (this.data) return Promise.resolve(this.data); return new Promise(resolve => { this.http.get('path/to/data.json') .map(res => res.json()).subscribe(data => { this.data = data; resolve(this.data); }); }); } }
/95
C O N D I T I O N A L S
67
<div *ngIf="someBoolean">Hello 1</div>
<div [ngSwitch]="someValues"> <p *ngSwitchWhen="1">Paragraph 1</p> <p *ngSwitchWhen="2">Paragraph 2</p> <p *ngSwitchWhen="3">Paragraph 3</p> <p *ngSwitchDefault>Paragraph</p> </div>
/95
C O N D I T I O N A L S
68
<div *ngIf="someBoolean">Hello 1</div>
<div [ngSwitch]="someValues"> <p *ngSwitchWhen="1">Paragraph 1</p> <p *ngSwitchWhen="2">Paragraph 2</p> <p *ngSwitchWhen="3">Paragraph 3</p> <p *ngSwitchDefault>Paragraph</p> </div>
<div [hidden]="someBoolean">Hello 2</div>
/95
C O N D I T I O N A L S
69
<div *ngIf="someBoolean">Hello 1</div>
<div [ngSwitch]="someValues"> <p *ngSwitchWhen="1">Paragraph 1</p> <p *ngSwitchWhen="2">Paragraph 2</p> <p *ngSwitchWhen="3">Paragraph 3</p> <p *ngSwitchDefault>Paragraph</p> </div>
<div [hidden]="someBoolean">Hello 2</div>
<div [class.my-custom-class]="someBoolean">Hello 3</div>
/95
N AV I G AT I O N
• Pop and push to history stack
• push(SomePage) – add to the top of stack
• pop() – delete last page from the stack
71
/95
N AV I G AT I O N E X A M P L E
73
<ion-navbar *navbar> <ion-title>movies</ion-title> </ion-navbar>
<ion-content padding class="movies"> <button class="positive" (click)="showDetail()"> Go to detail </button> </ion-content>
app/pages/movies/movies.html
/95
N AV I G AT I O N E X A M P L E
74
<ion-navbar *navbar> <ion-title>movies</ion-title> </ion-navbar>
<ion-content padding class="movies"> <button class="positive" (click)="showDetail()"> Go to detail </button> </ion-content>
Call method for showing another page
app/pages/movies/movies.html
/95
N AV I G AT I O N E X A M P L E
75
<ion-navbar *navbar> <ion-title>movie-detail</ion-title> </ion-navbar>
<ion-content padding class="movie-detail"> <button class="positive" (click)="goBack()"> Go back </button> </ion-content>
app/pages/movie-detail/movie-detail.html
/95
N AV I G AT I O N E X A M P L E
76
<ion-navbar *navbar> <ion-title>movie-detail</ion-title> </ion-navbar>
<ion-content padding class="movie-detail"> <button class="positive" (click)="goBack()"> Go back </button> </ion-content>
Call method for going back
app/pages/movie-detail/movie-detail.html
/95
N AV I G AT I O N – G O T O PA G E
77
import {Page, NavController} from 'ionic-angular'; import {MovieDetailPage} from '../movie-detail/movie-detail'
@Page({ templateUrl: 'build/pages/movies/movies.html', }) export class MoviesPage { static get parameters() { return [[NavController]]; }
constructor(nav) { this.nav = nav; } showDetail() { this.nav.push(MovieDetailPage) } }
app/pages/movies/movies.js
/95
N AV I G AT I O N – G O T O PA G E
78
import {Page, NavController} from 'ionic-angular'; import {MovieDetailPage} from '../movie-detail/movie-detail'
@Page({ templateUrl: 'build/pages/movies/movies.html', }) export class MoviesPage { static get parameters() { return [[NavController]]; }
constructor(nav) { this.nav = nav; } showDetail() { this.nav.push(MovieDetailPage) } }
app/pages/movies/movies.js Import
/95
N AV I G AT I O N – G O T O PA G E
79
import {Page, NavController} from 'ionic-angular'; import {MovieDetailPage} from '../movie-detail/movie-detail'
@Page({ templateUrl: 'build/pages/movies/movies.html', }) export class MoviesPage { static get parameters() { return [[NavController]]; }
constructor(nav) { this.nav = nav; } showDetail() { this.nav.push(MovieDetailPage) } }
app/pages/movies/movies.js Import
Dependency injection
/95
N AV I G AT I O N – G O T O PA G E
80
import {Page, NavController} from 'ionic-angular'; import {MovieDetailPage} from '../movie-detail/movie-detail'
@Page({ templateUrl: 'build/pages/movies/movies.html', }) export class MoviesPage { static get parameters() { return [[NavController]]; }
constructor(nav) { this.nav = nav; } showDetail() { this.nav.push(MovieDetailPage) } }
app/pages/movies/movies.js Import
Dependency injection
Save as class variable
/95
N AV I G AT I O N – G O T O PA G E
81
import {Page, NavController} from 'ionic-angular'; import {MovieDetailPage} from '../movie-detail/movie-detail'
@Page({ templateUrl: 'build/pages/movies/movies.html', }) export class MoviesPage { static get parameters() { return [[NavController]]; }
constructor(nav) { this.nav = nav; } showDetail() { this.nav.push(MovieDetailPage) } }
app/pages/movies/movies.js Import
Dependency injection
Save as class variable
Push MovieDetailPage to the stack
/95
N AV I G AT I O N – G O T O PA G E
82
import {Page, NavController} from 'ionic-angular'; import {MovieDetailPage} from '../movie-detail/movie-detail'
@Page({ templateUrl: 'build/pages/movies/movies.html', }) export class MoviesPage { static get parameters() { return [[NavController]]; }
constructor(nav) { this.nav = nav; } showDetail() { this.nav.push(MovieDetailPage) } }
app/pages/movies/movies.js Import
Dependency injection
Save as class variable
Push MovieDetailPage to the stack
/95
N AV I G AT I O N – G O B A C K
83
import {Page, NavController} from 'ionic-angular';
@Page({ templateUrl: 'build/pages/movie-detail/movie-detail.html', }) export class MovieDetailPage { static get parameters() { return [[NavController]]; }
constructor(nav) { this.nav = nav; }
goBack() { this.nav.pop() } }
app/pages/movie-detail/movie-detail.js
/95
N AV I G AT I O N – G O B A C K
84
import {Page, NavController} from 'ionic-angular';
@Page({ templateUrl: 'build/pages/movie-detail/movie-detail.html', }) export class MovieDetailPage { static get parameters() { return [[NavController]]; }
constructor(nav) { this.nav = nav; }
goBack() { this.nav.pop() } }
app/pages/movie-detail/movie-detail.js
Pop last page from the stack
/95
N AV I G AT I O N – G O T O PA G E W I T H PA S S I N G PA R A M S
85
import {Page, NavController} from 'ionic-angular'; import {MovieDetailPage} from '../movie-detail/movie-detail'
@Page({ templateUrl: 'build/pages/movies/movies.html', }) export class MoviesPage { static get parameters() { return [[NavController]]; }
constructor(nav) { this.nav = nav; }
showDetail() { this.nav.push(MovieDetailPage, { id: 4 }) } }
/95
N AV I G AT I O N – G O T O PA G E W I T H PA S S I N G PA R A M S
86
import {Page, NavController} from 'ionic-angular'; import {MovieDetailPage} from '../movie-detail/movie-detail'
@Page({ templateUrl: 'build/pages/movies/movies.html', }) export class MoviesPage { static get parameters() { return [[NavController]]; }
constructor(nav) { this.nav = nav; }
showDetail() { this.nav.push(MovieDetailPage, { id: 4 }) } }
Second parameter is an object with params
/95
N AV I G AT I O N – G E T PA R A M S
87
import {Page, NavController, NavParams} from 'ionic-angular';
@Page({ templateUrl: 'build/pages/movie-detail/movie-detail.html', }) export class MovieDetailPage { static get parameters() { return [[NavController], [NavParams]]; }
constructor(nav, params) { this.nav = nav; this.params = params; console.log("ID: " + this.params.get("id")); }
goBack() { this.nav.pop(); } }
/95
N AV I G AT I O N – G E T PA R A M S
88
import {Page, NavController, NavParams} from 'ionic-angular';
@Page({ templateUrl: 'build/pages/movie-detail/movie-detail.html', }) export class MovieDetailPage { static get parameters() { return [[NavController], [NavParams]]; }
constructor(nav, params) { this.nav = nav; this.params = params; console.log("ID: " + this.params.get("id")); }
goBack() { this.nav.pop(); } }
Import
/95
N AV I G AT I O N – G E T PA R A M S
89
import {Page, NavController, NavParams} from 'ionic-angular';
@Page({ templateUrl: 'build/pages/movie-detail/movie-detail.html', }) export class MovieDetailPage { static get parameters() { return [[NavController], [NavParams]]; }
constructor(nav, params) { this.nav = nav; this.params = params; console.log("ID: " + this.params.get("id")); }
goBack() { this.nav.pop(); } }
Import
Dependency injection
/95
N AV I G AT I O N – G E T PA R A M S
90
import {Page, NavController, NavParams} from 'ionic-angular';
@Page({ templateUrl: 'build/pages/movie-detail/movie-detail.html', }) export class MovieDetailPage { static get parameters() { return [[NavController], [NavParams]]; }
constructor(nav, params) { this.nav = nav; this.params = params; console.log("ID: " + this.params.get("id")); }
goBack() { this.nav.pop(); } }
Import
Dependency injection
Save as class variable
/95
N AV I G AT I O N – G E T PA R A M S
91
import {Page, NavController, NavParams} from 'ionic-angular';
@Page({ templateUrl: 'build/pages/movie-detail/movie-detail.html', }) export class MovieDetailPage { static get parameters() { return [[NavController], [NavParams]]; }
constructor(nav, params) { this.nav = nav; this.params = params; console.log("ID: " + this.params.get("id")); }
goBack() { this.nav.pop(); } }
Import
Dependency injection
Save as class variable
Get ID from params
/95
@janvaclavik
J A N VÁ C L AV Í K
@danielrys
D A N I E L R Y S
W W W. U S E R T E C H N O L O G I E S . C O M95