Raúl Jiménez
@elecash
Angular GDE
videogular
google partner
toptal partner
tu aplicación es un árbol de componentes
Application es un componente
import {Component} from '@angular/core';
@Component({
/* configuration */
})
class Application {
/* ... */
}
Application contiene Toolbar
Application contiene Toolbar
// application.ts
import {Component} from '@angular/core';
import {Toolbar} from './components/toolbar/toolbar';
@Component({
selector: 'my-root'
template: `<my-toolbar></my-toolbar>`,
directives: [ Toolbar ]
})
export class Application { /* ... */ }
<!-- index.html -->
<my-root>
Your application is loading...
</my-root>
arrancamos la aplicación para nuestra plataforma
import {Component} from '@angular/core';
import {bootstrap} from '@angular/platform-browser-dynamic';
@Component({
/* configuration */
})
class Application {
/* ... */
}
bootstrap(Application, [ /* deps */ ])
capturamos cuando se crea un componente con ngOnInit
import {Component, OnInit} from '@angular/core';
@Component({
/* configuration */
})
class Application implements OnInit {
/* ... */
ngOnInit() { /* ... */ }
}
ciclo de vida entero de un componente
class Application {
ngOnInit() {}
ngOnDestroy() {}
ngDoCheck() {}
ngOnChanges(changes) {}
ngAfterContentInit() {}
ngAfterContentChecked() {}
ngAfterViewInit() {}
ngAfterViewChecked() {}
}
los decorators añaden expresividad a tus clases
import {Component} from '@angular/core';
@Component({
selector: 'my-toolbar',
templateUrl: 'comps/toolbar/toolbar.html',
styleUrls: ['comps/toolbar/toolbar.css']
})
class Toolbar {
isOpen:boolean = false;
user:string = null;
/* ... */
}
bindings unidireccionales
<!-- comps/toolbar/toolbar.html -->
<div [ngClass]="{active: isOpen, disabled: !isOpen}">
<div *ngIf="user">Hello {{ user }}.</div>
<div *ngIf="!user">Login</div>
</div>
bindings de propiedades con @input()
<!-- application.html -->
<my-toolbar [isOpen]="isToolbarOpen"></my-toolbar>
import {Component, Input} from '@angular/core';
@Component({
selector: 'my-toolbar',
templateUrl: 'comps/toolbar/toolbar.html',
styleUrls: ['comps/toolbar/toolbar.css']
})
class Toolbar {
@Input() isOpen:boolean = false;
user:string = null;
/* ... */
}
capturar eventos con (event)
<!-- comps/toolbar/toolbar.html -->
<div [ngClass]="{active: isOpen, disabled: !isOpen}">
<div *ngIf="user">Hello {{ user }}.</div>
<div *ngIf="!user" (click)="onClickLogin()">Login</div>
</div>
import {Component, Input} from '@angular/core';
@Component({/* ... */})
class Toolbar {
@Input() isOpen:boolean = false;
user:string = null;
onClickLogin() {
/* ... */
}
}
emitir eventos con @Output()
<!-- application.html -->
<my-toolbar [isOpen]="isToolbarOpen"
(onClickLogin)="doSomethingOnApp()">
</my-toolbar>
import {Component, Input, Output, EventEmitter} from '@angular/core';
@Component({/* ... */})
class Toolbar {
@Input() isOpen:boolean = false;
@Output('onClickLogin') onClickLogin:EventEmitter<any> = new EventEmitter();
user:string = null;
onClickLogin() {
this.onClickLogin.next(event.target);
}
}
bindings de dos direcciones con [(ngModel)]
<!-- comps/toolbar/toolbar.html -->
<div [ngClass]="{active: isOpen, disabled: !isOpen}">
<div *ngIf="user">Hello {{ user }}.</div>
<div *ngIf="!user">
<input type="text" [(ngModel)]="username">
<input type="password" [(ngModel)]="password">
<div (click)="onClickLogin()">Login</div>
</div>
</div>
components
<my-toolbar></my-toolbar>
import {Component} from '@angular/core';
@Component({
selector: 'my-toolbar',
templateUrl: 'comps/toolbar/toolbar.html',
styleUrls: ['comps/toolbar/toolbar.css']
})
class Toolbar {
/* ... */
}
directivas estructurales
<my-card
*ngIf="isFooBar"
*ngFor="let card of dataStore.items;
trackBy:customTrackBy">
{{ card }}
</my-card>
<!-- es equivalente a esto -->
<template
ngFor
let-card
[ngForOf]="dataStore.items"
[ngForTrackBy]="customTrackBy">
<my-card>{{ card }}</my-card>
</template>
attributes
<my-progress-bar [style.width]="progress + '%'">
<span [blink]>{{ card + '%' }}</span>
</my-progress-bar>
import {Component} from '@angular/core';
@Component({
selector: '[blink]'
})
class Blink {
/* ... */
}
los pipes son parecidos a los filters de Angular 1.X
DatePipe
UpperCasePipe
LowerCasePipe
CurrencyPipe
PercentPipe
etc...
los pipes son parecidos a los filters de Angular 1.X
<span>{{ username | trim }}</span>
import {Pipe, PipeTransform} from '@angular/core';
@Pipe({
name: 'trim'
})
export class TrimPipe implements PipeTransform {
transform(value: any) {
if (!value) {
return '';
}
return value.trim();
}
}
el nuevo router que se desarrolló ya está deprecated y uno nuevo va a salir en breve
los siguientes ejemplos son basados en el router deprecated ya que el nuevo aún no es estable
para usar el router has de incluirlo en el bootstrap como una dependencia
import {provide} from '@angular/core';
import { bootstrap } from '@angular/platform-browser-dynamic';
import {AppComponent} from './app.component';
import {
ROUTER_PROVIDERS,
PathLocationStrategy,
LocationStrategy // or HashLocationStrategy
} from '@angular/router-deprecated';
bootstrap(AppComponent, [
ROUTER_PROVIDERS,
provide(LocationStrategy, {
useClass: PathLocationStrategy // or HashLocationStrategy
})
]);
ya puedes asignar rutas a tus componentes
import { ROUTER_DIRECTIVES, RouteConfig } from '@angular/router-deprecated';
@Component({
selector: 'app',
template: `
<h1>Component Router</h1>
<nav>
<a [routerLink]="['Customers']">Customers</a>
<a [routerLink]="['Orders', {id: order.id}]">Orders</a>
</nav>
<router-outlet></router-outlet>
`,
directives: [ROUTER_DIRECTIVES]
})
@RouteConfig([
{ path: '/', name: 'Customers', component: CustomersComponent, useAsDefault: true },
{ path: '/orders/:id', name: 'Orders', component: OrdersComponent },
{ path: '/details/...', name: 'OrderDetails', component: DetailsComponent }
])
export class AppComponent {
constructor(private params: RouteParams) {
let id = this.params.get('id');
}
}
factories y services ya no existen, ahora solo hay providers
import { Component } from '@angular/core';
import { DataStore } from './my-store';
@Component({
selector: 'home',
providers: [ DataStore ],
//...
})
export class Home {
private data: any[];
constructor(data: DataStore){
this.data = data.someAPI();
}
}
los providers son clases inyectables
import {Injectable} from 'angular2/core';
@Injectable()
export class DataStore {
constructor() {}
someAPI() {
// ...
}
}
puedes configurar tus providers para que usen otras clases
import { Component, provide } from '@angular/core';
import { DataStore } from './my-store';
@Component({
providers: [ provide(DataStore, {useClass: MockedDataStore}) ]
})
export class Home { /* */ }