@josh2code

Qué vamos a ver

 Intro​

 TypeScript 

1

Angular2

 Arquitectura

 Angular2-basic

Starterkit

Let's code!

World

2

World

3

World

4

World

5

World

6

World

World

1-1

x

3

Introducción

  • SPA (Single Page Application) Framework 
  • Extiende etiquetas HTML.
    • ​Propia parte visual (HTML, CSS)
    • Propio comportamiento (javascritp)
  • Basado en Componentes
  • Recomendado TypeScript (puedes usar ES5/ES6 )
  • Injección de dependencias

Angular2 vs Angular1.x

  • Angular 2 es relativamente joven.
  • Angular 2 ha sido reimplementado, no es una evolución de AngularJS
  • Angular 2 no es compatible con AngularJS 1.x

$scope

ng-if

ng-app

ng-model

mobile

oriented

better

performance

x5

Olvida todo lo que conoces de AngularJS

World

2-1

x

3

Lenguajes

ES5

ES6

Puedes usar cualquier lenguaje que transpile tu código a Javascript, pero recomendamos usar TypeScript

Transpilar

Palabras ways

Resulta que el código de Typescript no se compila, se "transpila". En resumen, compila el typescript para dárselo al navegador en un idioma que entiende. ES5, ES6

  • Añade tipos estáticos a Javascript ES6
    • Inferencia de tipos (no hay que declararlos en muchos sitios)
    • Tipos opcionales (si no quieres, no lo usas)
  • El compilador genera código Javascript ES5 (compatible con los navegadores actuales)
  • Orientado a Objetos con clases (no como ES5)

{

Principales Características

  • Los programas son menos propensos a errores
  • Los IDEs y editores pueden: Autocompletar, Refactorizar, navegar a la definición...
  • Los tipos son opcionales
  • Se puede combinar js y ts

{

Ventajas

export class EntrenadorPokemon {
    private nombre:string;
    private pokeballs:number;

    constructor(nombre: string, 
                pokeballs: number) {
        this.nombre = nombre;
        this.pokeballs = pokeballs;
    }
    
    getNombre() {
        return this.nombre;
    }

    toString() {
        return "Nombre: "+ this.nombre + 
               ", Pokeballs: " + this.pokeballs;
    }    
}
function EntrenadorPokemon(nombre, pokeballs) {
    this.nombre = nombre;
    this.pokeballs = pokeballs;
}

EntrenadorPokemon.prototype.getNombre = 
    function(){
        return this.nombre;
};

EntrenadorPokemon.prototype.toString = 
    function(){
        return "Nombre: "+ this.nombre + 
               ", Pokeballs: " + this. pokeballs;
};

ES5

TypeScript

VS

Clases

import { EntrenadorPokemon } from "./EntrenadorPokemon";

let entrenadores = new Array<EntrenadorPokemon>();

entrenadores.push(new EntrenadorPokemon('Ash', 150);
entrenadores.push(new EntrenadorPokemon('Josh', 30);

for(let entrenador of entrenadores) {
    console.log(entrenador.getNombre());
}

entrenadores.forEach(entrenador => {
    console.log(entrenador);
});

Imports

  • En TS cada fichero tiene que importarse, existen módulos y componentes.
import { EntrenadorPokemon } from "./EntrenadorPokemon";

let entrenadores = new Array<EntrenadorPokemon>();

entrenadores.push(new EntrenadorPokemon('Ash', 150);
entrenadores.push(new EntrenadorPokemon('Josh', 30);

for(let entrenador of entrenadores) {
    console.log(entrenador.getNombre());
}

entrenadores.forEach(entrenador => {
    console.log(entrenador);
});

Variables

  • En TS las variables se declaran con let y tienen ámbito de bloque y no se pueden declarar dos veces. Se podría usar var (como JS), pero el ámbito sería la función y se podrían redeclarar
  • El tipo se puede declarar con : , es opcional, se puede inferir de la inicialización, pero es recomendable usar tipado.

Definición Atributos

class Goomba {

    private life: number;

    constructor(hearts: number) {
        this.life = hearts;
    }
}
class Goomba {
    constructor(private life: number) {
        ...
    }
}

Get & Set

class Goomba {

    private life: number;

    get life(): number {
        return this.life;
    }

    set life(hearts: number) {
        this.life = hearts;    
    }
}

how to use it

let enemy = new Goomba();

if(enemy.life == 0) {
    console.log('Goomba KO');

    enemy.life = 100;
} 

Multi tipo

let id: string | number;

id = 3; // Asignamos un numero
...
id = '3'; // Asignamos un string

if(typeof id === 'string'){
    ...
}

Objetos literales

interface Enemy {
    name: string;
    life?: number;
}
let enemy: Enemy;

enemy = {name: 'Woomba'};
enemy = {name: 'Woomba', life: 100}; 

World

3-1

x

3

ngular 2

componentes

import { Component } from '@angular/core';

@Component({
  selector: 'world', // Nombre del tag html
  providers: [], // Servicios
  styleUrls: [], // Url de los estilos
  templateUrl: './world.component.html'
})
export class WorldComponent {

}

ngular 2

Modulos

Angular tiene al menos un módulo, ya sea de root o funcionalidad, es una clase con un decorador @ngModule

ngular 2

¿Cómo se organizan los componentes?

Modulos

ngular 2

eventos

<button (click)="jump()"></button>

ngular 2

Atributos

import { Component } from '@angular/core';

@Component({
    selector: 'app-root',
    templateUrl: './app.component.html'
})

export class AppComponent {
    name = 'Mario';
    imageUrl = 'assets/img/mario.png';
}

ngular 2

<h1>It is me {{name}}</h1>
<img [src]="imgUrl"/>

app.component.html

app.component.ts

Data Binding

DOM

Component

{{ value }}

[property] = *value*

(event) = *handler*

[(event)] = *handler*

ngular 2

Comunicación

ngular 2

Configuración de propiedades (Padre -> Hijo)

<world [name]="worldName"></world>
export class AppComponent {
    worldName = 'World 1-1';
}
import {Component, Input} from '@angular/core';

export class WorldComponent {
    @Input()
    private name: string;
}
<h1>{{name}}</h1>

app.component.ts

app.component.html

world.component.ts

world.component.html

Comunicación

ngular 2

Envío de Eventos (Hijo -> Padre)

<world [name]="worldName" (changeName)='changeWorld($event)'></world>
export class AppComponent {
    worldName:string = 'World 1-1';

    changeWorld(name: string) {
        this.worldName = name;        
    }
}
import {Component, Input, Output, EventEmitter} from '@angular/core';

export class WorldComponent {
    @Input()
    private name: string;

    @Output()
    changeName = new EventEmitter<string>();

    click(level) {
        this.changeName.next(level);
    }
}
<h1>{{name}}</h1>
<button (click)='click("World 1-2")'>Next level</button>

app.component.ts

app.component.html

world.component.ts

world.component.html

Id

<input type="text" #field1 />

<button (click)="validate(field1.value)">Valida el campo</button>

ngular 2

#field1 es un id que le hemos dado al input. Además podemos usarlo en otro sitio! Awesome!

Directivas

Structure

Attribute

<li *ngFor="let enemy of enemies">
</li>
<enemy *ngIf="hasLife">
</enemy>

*ngFor

*ngIf

<div [ngClass]="['bold-text', 'green']"></div>
<div [ngClass]="'italic-text blue'"></div>
<div [ngClass]="{'small-text': true, 'red': true}"></div>

ngClass

ngStyle

¡Podemos crear las nuestras propias!

...

...

ngular 2

Ciclos de vida de un componente

  • ngOnChanges - called when an input binding value changes
  • ngOnInit - after the first ngOnChanges
  • ngDoCheck - after every run of change detection
  • ngAfterContentInit - after component content initialized
  • ngAfterContentChecked - after every check of component content
  • ngAfterViewInit - after component's view(s) are initialized
  • ngAfterViewChecked - after every check of a component's view(s)
  • ngOnDestroy - just before the component is destroyed

ngular 2

import { Component } from 'angular2/core';

@Component({
    selector: 'app',
    templateUrl: 'app.component.html'
})

export class AppComponent {

}

Decoradores

@Component es un decorador que le dice a Angular que la clase a la que hace referencia es un componente.

ngular 2

Services

ngular 2

Services

ngular 2

  • Es habitual que haya un único objeto de cada servicio en la aplicación (singleton)
  • Es decir, todos los componentes comparten "el mismo" servicio
  • De esa forma los servicios mantienen el estado de la aplicación

Services

ngular 2

  • Se puede hacer que un servicio no sea compartido entre todos los componentes de la aplicación (no sea singleton)
  • Se puede crear un servicio exclusivo para un componente y sus hijos
  • En vez de declarar el servicio en los providers de @NgModule se declara en el @Component
  • Puede ser compartido por el componente padre y por sus componentes hijos (incluido en él)

Servicios

import { Injectable } from '@angular/core';

@Injectable()
export class BlockService {

  getCoins() { 
    return 100; 
  }
}

ngular 2

Servicio en module

import { NgModule } from '@angular/core';
import { BlockCoins } from './blockCoins.service';

@NgModule({
    declarations: [AppComponent],
    imports: [BrowserModule],
    providers: [BlockCoins]
})

export class AppModule{

}

ngular 2

Servicio exclusivo para un componente

import { Component } from '@angular/core';
import { BlockCoins } from './blockCoins.service';

@Component({
    selector: 'app-root',
    templateUrl: './app.component.html',
    providers: 'BlockCoins'
})

export class AppComponent {
    constructor (private blockCoins: BlockCoins) {
    }

}

ngular 2

Peticiones http en un servicio

ngular 2

  • Callbacks
  • Promesas
  • Observables

Peticiones http en un servicio

ngular 2

Callbacks

Hay muchas librerías implementadas así. Ya no se recomienda este enfoque porque es más limitado.

Peticiones http en un servicio

ngular 2

Promesas

La forma estándar en ES6. La forma recomendada si la funcionalidad es suficiente.

Peticiones http en un servicio

ngular 2

Observables

Implementados en la librería RxJS. Es la forma mas completa y mas compleja.

Router

ngular 2

<router-outlet></router-outlet>

<a [routerLink]="/world1"></a>

Así invocamos el cambio

Este es el contenedor donde se cargará el componente o módulo que indique el router

Router

ngular 2

import { Routes, RouterModule } from '@angular/router';

import { WorldComponent } from './world.component';
import { WorldDetailComponent } from './worldDetail.component';

const appRoutes = [
    { path: 'world1', component: WorldComponent },
    { path: 'world/:id', component: WorldDetailComponent },
    { path: '', component: WorldComponent }
]

export const routing = RouterModule.forRoot(appRoutes);

app.routes.ts

Configuración Router

ngular 2

...
import { routing } from './app.routing';


@NgModule({
    declarations: [AppComponent, WorldComponent],
    imports: [BrowserModule, FormsModule, HttpModule, JsonModule, routing],
    bootstrap: [AppComponent],
    providers: [BlockCoinsService]
})

export class AppModule {}

app.module.ts

World

4-1

x

3

Arquitectura

ngular 2

Holy Style Guide

ngular 2

World

5-1

x

3

Starter kit

ngular 2 Basic

git clone https://github.com/serenity-frontstack/angular2-basic.git
cd angular2-basic
npm install
npm run serve

Debería abrir el starter kit en el navegador

Starter kit

ngular 2 Basic

  • config/ Archivos de configuración de la app
  • dist/ Carpeta de distribución de la app
  • docs/ Documentación de la app
  • e2e/ Test funcionales de la app
  • i18n/ Traducciones
  • src/ Código fuente de la app

src/

ngular 2 Basic

  • app/ código fuente de la app
  • assets/ recursos necesarios de la app
  • meta/ metainformación
  • index.html Página inicial

app/

ngular 2 Basic

  • modules/ módulos lazy load con funcionalidad
  • shared/ componentes reutilizables
  • shell/ estructura básica de la aplicación (esqueleto)
  • app.module.ts Módulo inicial
  • app.routes.ts Rutas por defecto
  • index.ts fichero de definición (barrel)

app/

ngular 2 Basic

  • Los módulos son una parte funcional de nuestra aplicación, contienen componentes, servicios, pipes, propios y además pueden contener otros módulos.
  • El app shell es una manera de cargar solo lo necesario en la primera carga y el resto de cosas las cargaremos con lazy load.
  • Cada módulo puede definir sus propias rutas.

Usos

ngular 2 Basic

  • npm run serve
  • npm run build
  • npm run test
  • npm run protractor
  • npm run typedoc
  • ....
  • ....

Revisa el package.json para ver los usos

World

6-1

x

3

ngular 2

Vamos a crear estos elementos en Angular 2

ngular 2

El primer paso para abordar una aplicación por componentes es identificar patrones, que cosas se reutilizan y cuales no.

Servicio

Personaje

Enemigo

Mundo

ngular 2

Vamos a empezar creando un nuevo Módulo que será cargado en nuestra aplicación de manera Lazy Load

Creamos una carpeta que se llame +superAngular2 dentro de la carpeta app/modules/

El + delante del nombre del modulo es una convención para indicar que ese módulo se cargará por Lazy Load

ngular 2

Vamos a empezar creando un nuevo Módulo que será cargado en nuestra aplicación de manera Lazy Load

import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';


@NgModule({
  declarations: [],
  imports: [
    CommonModule
  ]
})

export class SuperAngular2Module {
}

app/modules/+superAngular2/superAngular2.module.ts

 

ngular 2

Empezamos por el primer componente

world.component.ts

Componente World

import { Component } from '@angular/core';

@Component({
  selector: 'world', 
  providers: [],
  styleUrls: [],
  templateUrl: './world.component.html'
})
export class WorldComponent {

}

ngular 2

Componente Goomba

ngular 2

Ahora es tu turno, crea un componente Goomba. Goomba es un enemigo del juego Super Mario.

Añade un Goomba al componente world

ngular 2

<h1>World</h1>
<goomba></goomba>

world.component.html

Añade el componente al módulo superAngular2.module.ts en la sección declarations.

Crea 3 enemigos woompa

ngular 2

Ejercicio 1

Crea el componente personaje

ngular 2

Ejercicio 2

*Ten en cuenta que Mario y Luigi son 2 personajes igualmente jugables, con lo que tendrás que hacer que tu componente sea flexible para definir el nombre del personaje

Añade a Mario y Luigi al mundo

ngular 2

Ejercicio 3

Mario y Luigi pueden saltar. Crea un boton que al hacer click saque por consola que Mario o Luigi ha saltado

ngular 2

Ejercicio 4

Vamos a aplastar esos Goomba. Crea un botón que permita al goomba ser aplastado con un click y que como consecuencia, el goomba desaparezca del mundo.

ngular 2

Ejercicio 6

button

Vamos a conseguir unas moneditas. Vamos a crear un servicio que suministrará a Mario y Luigi unas monedas cuando se golpee. Haz que se muestre el total de monedas de cada personaje.

ngular 2

Ejercicio 7

Vamos hacer que el personaje sea quien aplaste al Goomba. Como beneficio, cada goomba que aplaste recibirá 15 monedas mas.

ngular 2

Ejercicio 8

El módulo +superAngular2 que hemos creado es reutilizable en cualquier aplicación Angular 2. Este módulo contiene toda la funcionalidad imprescindible para su uso.

ngular 2

Reutilización

ngular 2

Todos los ejercicios resueltos

Esto es solo el principio

ngular 2

¿Preguntas?

ngular 2

Sorry Mario but the princess is in another castle!

Made with Slides.com