Full Stack Developer
CTO @ Kaleidoscope Srl
@fmriggio
L'esempio userà le API prese da pokeapi.co.
npm install -g nativescript
tns --version
tns create pokeproject --ng --appid it.kaleidoscope.pokeproject
tns platform add ios
tns platform add android
/** ---- app.module.ts ---- **/
// Import the library
import { NativeScriptHttpModule } from "nativescript-angular/http";
// Inject the module
@NgModule({
[...]
imports: [NativeScriptModule, NativeScriptHttpModule]
})
/** ---- app.component.ts ---- **/
// Imports
import { Component, OnInit } from "@angular/core";
@Component({
selector: "my-app",
templateUrl: "app.component.html"
})
export class AppComponent implements OnInit {
public constructor() { ... }
public ngOnInit() { ... }
public showInformation(index: number) { ... }
public showDialog(data: Array<string>) { ... }
}
/** ---- app.component.ts ---- **/
// Imports
import { Http } from "@angular/http";
import "rxjs/Rx";
export class AppComponent implements OnInit {
public pokemon: Array<any>;
public constructor(private http: Http) { ... }
public ngOnInit() {
this.http.get("https://pokeapi.co/api/v2/pokemon?limit=151")
.map(result => result.json())
.flatMap(result => result.results)
.subscribe(result => {
this.database.getDatabase().createDocument(result);
this.pokemon.push(result);
}, error => {
console.error(error);
});
}
}
/** ---- app.component.html ---- **/
<ActionBar title="PokeProject"></ActionBar>
<StackLayout>
</StackLayout>
I layout in NativeScript sono descritti utilizzando una serie di tag XML (https://docs.nativescript.org/ui/basics).
Il layout della nostra app è composto da un header e da un layout verticale.
L'header : <ActionBar/> e il vertical layout <StackLayout/>
/** ---- app.component.html ---- **/
<GridLayout rows="auto" columns="auto, *, auto">
</GridLayout>
La nostra app presenta principalmente una lista.
Useremo il layout di tipo griglia, per mostrare la lista di pokemon .(https://docs.nativescript.org/cookbook/ui/layouts/grid-layout).
Il layout configurato come da codice, permette di avere rows con altezze diverse (che si adattano da sole) e colonne dove la prima e terza colonna hanno una larghezza fissa (auto) e la centrale ha una larghezza che si adatta in automatico allo spazio restante.
/** ---- app.component.html ---- **/
<ListView [items]="pokemon">
<template let-monster="item" let-index="index">
<GridLayout/>
</template>
</ListView>
Il tag template verrà ripetuto per ogni elemento dell'array pokemon e, durante il ciclo, viene assegnato un elemento dell'array all'oggetto monster.
/** ---- app.component.html ---- **/
<GridLayout rows="auto" columns="auto, *, auto" margin="15">
<Label row="0" col="0" class="pokemon-number" text="{{ index + 1 }}." marginRight="10"></Label>
<Label row="0" col="1" class="pokemon-name" [text]="monster.name" ></Label>
<Image row="0" col="2" class="pokemon-image" src="~/images/{{index + 1}}.png" ></Image>
</GridLayout>
/** ---- app.css ---- **/
.pokemon-number {
font-weight: bold;
}
.pokemon-name {
text-transform: capitalize;
}
.pokemon-image {
animation-name: pokemon-image;
animation-duration: 1s;
animation-delay: 1s;
opacity: 0;
}
@keyframes pokemon-image {
from { opacity: 0; transform: rotate(0deg); }
to { opacity: 1; transform: rotate(360deg); }
}
/** ---- app.component.html ---- **/
<GridLayout [...] (tap)="showInformation(index+1)">
[...]
</GridLayout>
/** ---- app.component.ts ---- **/
[...]
public showInformation(index: number) {
this.http.get("https://pokeapi.co/api/v2/pokemon/" + index)
.map(result => result.json())
.flatMap(result => result.types)
.map(result => (<any> result).type.name)
.toArray()
.subscribe(result => {
this.showDialog(result);
}, error => {
console.error(error);
});
}
[...]
/** ---- app.component.ts ---- **/
// Import the library
// https://docs.nativescript.org/cookbook/ui/dialogs
import dialogs = require("ui/dialogs");
[...]
public showDialog(data: Array<string>) {
dialogs.alert({
title: "Information",
message: "Questo pokemon è del tipo " + data.join(", "),
okButtonText: "OK"
});
}
[...]
tns plugin add nativescript-couchbase
NativeScript permette di aggiungere plugin nativi (come cordova) accessibili tramite API javascript. Qui una lista di possibili plugins: https://docs.nativescript.org/plugins/plugins.
Ogni plugin, inoltre, è provvisto dal file delle definizioni typescript, da aggiungere al file delle referenze.
/// <reference path="./node_modules/nativescript-couchbase/couchbase.d.ts" />
/** ---- database.ts ---- **/
// CREAZIONE DEL PROVIDER DEL DB
import { Couchbase } from 'nativescript-couchbase';
export class Database {
private db: any;
public constructor() {
this.db = new Couchbase("db");
}
public getDatabase() {
return this.db;
}
}
/** ---- app.component.ts ---- **/
// INIEZIONE NELLA APP
@Component({
selector: "my-app",
templateUrl: "app.component.html",
providers: [Database]
})
export class AppComponent implements OnInit {
[...]
public constructor(private http: Http, private database: Database) { [...] }
}
/** ---- app.component.ts ---- **/
[...]
public ngOnInit() {
let rows = this.database.getDatabase().executeQuery("pokemon");
if (rows.length == 0) {
this.http.get("https://pokeapi.co/api/v2/pokemon?limit=151")
.map(result => result.json())
.flatMap(result => result.results)
.subscribe(result => {
this.database.getDatabase().createDocument(result);
this.pokemon.push(result);
}, error => {
console.error(error);
});
} else {
for (let i = 0; i < rows.length; i++) {
this.pokemon.push(rows[i]);
}
}
}
[...]
/** ---- database.ts ---- **/
[...]
public constructor() {
this.db = new Couchbase("db");
this.db.createView("pokemon", "1", (document, emitter) => {
emitter.emit(document._id, document);
});
}
[...]
Dal sito di CouchBase:
A MapReduce View will emit a key-value pair. Logic can be placed around the emitter to make the views more specific.
// NativeScript XML tag
<ActionBar title="Sign up"></ActionBar>
// Controller Obj-c (mappato in node_modules/tns-core-modules/ui/frame/frame.ios.js)
UINavigationController
// Componente UI Obj-c (mappato in node_modules/tns-core-modules/ui/action-bar/action-bar.ios.js)
UINavigationBar
// Modificare lo stile della ActionBar per iOS
if (page.ios) {
var navigationBar = frameModule.topmost().ios.controller.navigationBar;
navigationBar.barStyle = UIBarStyle.UIBarStyleBlack;
}
Documentazione di NativeScript
http://docs.nativescript.org/
Lista dei plugins (certificati da Telerik)
http://plugins.nativescript.org/
Plugin CouchBase
https://github.com/couchbaselabs/nativescript-couchbase
Performances (web-view)
https://github.com/mlynch/pgday-eu-2017-perf/blob/master/web-perf-2017.pdf
Laravel-based
Multilanguage
Blazing fast