Programar en Typescript tiene muchas ventajas sobre Javascript. Las más importantes son:
- chequeo de tipos estático (aunque mantiene la posibilidad de tipos dinámicos de Javascript)
- uso de interfaces, clases, herencia y genéricos
- funciones cursor (arrow)
- parámetros por defecto y opcionales
El hecho de que el código Typescript pueda convertirse a Javascript hace que sea posible utilizar este lenguaje en nuestros proyectos Nativescript. Veamos cómo.
El objetivo de este artículo es demostrar lo sencillo que es crear una aplicación Nativescript desde cero, con datos enlazados al modelo de una forma mucho más sencilla que en Javascript. No entraré en muchas explicaciones sobre los detalles del código (se irán viendo en posteriores artículos), pero es bastante sencillo de seguir.
Es importante hacer notar que el uso de Typescript no implica utilizar Angular. Ni mucho menos, en el ejemplo que hago a continuación no se utiliza Angular en ningún momento, simplemente se utiliza Typescript en sustitución de Javascript.
Es importante hacer notar que el uso de Typescript no implica utilizar Angular. Ni mucho menos, en el ejemplo que hago a continuación no se utiliza Angular en ningún momento, simplemente se utiliza Typescript en sustitución de Javascript.
Definición del proyecto
El proyecto que vamos a crear es muy sencillo. El prototipo en papel (como a mí me gusta) se muestra a continuación:
En la primera pantalla (a la que llamaremos main) se muestra la oferta del día y un botón para navegar a la pantalla donde se muestran las ofertas para los próximos días. Llamaremos next a esta segunda pantalla.
Instalar Typescript
Instalemos Typescript en nuestro equipo:
npm install -g typescript
Si ya estuviera instalado, este comando actualizará a la última versión.
Comprobemos que está correctamente instalado y la versión:
tsc --version
Crear el proyecto Nativescript
Ir al directorio base y crear el proyecto usando la plantilla typescript:
tns create OfertaDelDia --template typescript
Lo primero que vemos es que el proyecto no tiene un fichero app/app.js como ocurre en los proyectos Nativescript con Javascript, sino que el fichero se llama app/app.ts, o sea, un fichero Typescript.
El contenido de este fichero es:
import * as app from 'application';
app.start({
moduleName: 'main/main'
});
Página main
Creamos una carpeta app/main para los ficheros de la página main.
Creamos el fichero app/main/main.xml:
<Page xmlns="http://schemas.nativescript.org/tns.xsd" navigatingTo="onPage">
<StackLayout>
<Label text="{{ today }}" class="today" />
<Label text="{{ dayOffer }}" class="day-offer" textWrap="true" />
<Label text="{{ todayPrice }}" class="today-price" />
<Label text="{{ yesterdayPrice }}" class="yesterday-price" />
<Button text="Próximos días..." tap="onNextDays" />
</StackLayout>
</Page>
El atributo Page.navigatingTo define la rutina que será invocada cada vez que entremos en la página. Esta rutina se define en el fichero main.ts
Esta página simplemente contiene un StackLayout con cuatro Labels y un Button. Los labels muestran texto (atributo text) procedente del modelo, es decir, datos del objeto Observable que definiremos en el fichero main-view-model.ts Este objeto modelo tendrá al menos las propiedades today, dayOffer, price y yesterdayPrice.
El atributo class indica el estilo aplicable. Estos estilos se definen en el fichero main.css
Creamos el fichero app/main/main.ts:
import { EventData } from "data/observable";
import { Page } from "ui/page";
import { MainViewModel } from "./main-view-model";
import frame = require('ui/frame');
export function onPage(args: EventData) {
var page = <Page>args.object;
page.bindingContext = new MainViewModel();
setTimeout(
function() {
console.log('timeout');
page.bindingContext.set('todayPrice', 'Hoy 49€');
},
5000
);
}
export function onNextDays() {
frame.topmost().navigate('next/next');
}
En este fichero se define la función que se llamará cada vez que entremos en la página: onPage(). Esta función recibe entre sus argumentos el objeto Page, al cual enlazamos un bindingContext, el cual será un nuevo objeto de la clase MainViewModel. Este objeto sirve para enlazar datos de ese modelo con controles de la interfaz de usuario.
Por último, ponemos una ejecución diferida de Javascript (setTimeout) para cambiar el modelo después de 5 segundos. Cuando se ejecute esta función diferida, se actualiza el objeto modelo y por consiguiente se actualizará automáticamente la etiqueta asociada.
Creamos el fichero app/main/main.css:
Por último, ponemos una ejecución diferida de Javascript (setTimeout) para cambiar el modelo después de 5 segundos. Cuando se ejecute esta función diferida, se actualiza el objeto modelo y por consiguiente se actualizará automáticamente la etiqueta asociada.
Creamos el fichero app/main/main.css:
.day-offer {
font-size: 40px;
font-weight: bold;
text-align: center;
}
.today-price {
font-size: 30px;
font-weight: bold;
text-align: center;
}
.yesterday-price {
font-size: 20px;
text-align: center;
}
.today {
font-size: 12px;
text-align: center;
}
Button {
margin: 20px;
}
Creamos el fichero app/main/main-view-model.ts:
import observable = require("data/observable");
export class MainViewModel extends observable.Observable {
constructor() {
super();
this.set('dayOffer', 'Maleta de viaje Samsonite L3R');
this.set('todayPrice', 'Hoy 58€');
this.set('yesterdayPrice', 'Ayer 96€');
this.set('today', 'Lunes, 27 de julio');
}
}
Página next
Creamos una carpeta app/next para los ficheros de la página next.
Creamos el fichero app/next/next.xml:
<Page xmlns="http://schemas.nativescript.org/tns.xsd"
navigatingTo="onPage">
<Page.actionBar>
<ActionBar title="Ofertas próximos días" class="header">
<NavigationButton text="Back" android.systemIcon="ic_menu_back" tap="onBack" />
</ActionBar>
</Page.actionBar>
<DockLayout stretchLastChild="true">
<DockLayout dock="bottom">
<Button dock="right" text="Add" tap="onAdd" />
<TextField id="newText" class="input input-border" hint="New text" />
</DockLayout>
<ScrollView>
<ListView items="{{ items }}">
<ListView.itemTemplate>
<StackLayout>
<Label text="{{ $value.date }}" class="date" />
<Label text="{{ $value.offer }}" class="offer" />
</StackLayout>
</ListView.itemTemplate>
</ListView>
</ScrollView>
</DockLayout>
</Page>
Esta página es un poco más compleja que la anterior. En primer lugar contiene un DockLayout que incluye una lista de ofertas en la parte central, y un campo de texto junto con botón para añadir elementos, en la parte inferior. La lista de ofertas está enlazada al modelo, que será un array de objetos con dos campos: date y offer.
Creamos el fichero app/next/next.ts:
import { EventData } from "data/observable";
import { Page } from "ui/page";
import { NextViewModel } from "./next-view-model";
import frame = require('ui/frame');
import view = require("ui/core/view");
var page:Page = null;
var model:NextViewModel = null;
export function onPage(args: EventData) {
console.log('next.onPage');
page = <Page>args.object;
model = new NextViewModel();
page.bindingContext = model;
}
export function onBack() {
frame.topmost().goBack();
}
export function onAdd() {
let newTextTxt:any = view.getViewById(page, "newText");
console.log('Text=' + newTextTxt.text);
model.addItem('Hoy', newTextTxt.text);
newTextTxt.text = "";
}
Creamos el fichero app/next/next.css:
.offer {
font-size: 25px;
font-weight: bold;
text-align: center;
}
.date {
font-size: 14px;
text-align: left;
}
.header {
background-color: #333;
color: #fff;
}
Creamos el fichero app/next/next-view-model.ts:
import observable = require("data/observable");
import {ObservableArray} from 'data/observable-array';
export class NextViewModel extends observable.Observable {
public items:ObservableArray<object> = null;
constructor() {
super();
this.items = new ObservableArray();
this.items.push({date: 'Martes 28', offer: 'Portátil HP 400X' });
this.items.push({date: 'Miércoles 29', offer: 'Mochila Thule 3' });
this.items.push({date: 'Jueves 30', offer: 'iPhone 6S 32GB' });
this.set('items', this.items);
}
addItem(d:string, o:string) {
console.log('Add: ' + d + ',' + o);
if (o.length > 0) {
this.items.push({date:d, offer:o});
} else {
console.log("Empty string");
}
}
}
Ejecutar la aplicación
Arrancar el emulador Android o el simulador iOS, o bien Genymotion.
tns platform add android
tns platform add ios
tns run android --emulator
tns run ios --emulator
No hay comentarios:
Publicar un comentario