jueves, 5 de enero de 2017

MongoDb: Introducción

Bueno. ya estoy un poco cansado de Angular2 que es muuuuuy extenso, así que voy a dar una pequeña introducción de MongoDB, resumiendo a Romanian Coder.


1. Instalacion de MongoDB

Para ello vamos a ver lo que nos dice la web oficial de MongoDB para instalar en Ubuntu (en este caso ubuntu 16, y la versión 3.2 de MongoDB). Abrimos una ventana de terminal

1. Importar la clave pública para el gestor de paquetes.
sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 0C49F3730359A14518585931BC711F9BA15703C6
2. Crear la lista de fichero para mongo db (Ubuntu 16.04)
echo "deb [ arch=amd64,arm64 ] http://repo.mongodb.org/apt/ubuntu xenial/mongodb-org/3.4 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-3.4.list
3. Recargar la base de datos de paquetes
sudo apt-get update
4. Instalar los paquetes de MongoDB
sudo apt-get install -y mongodb-org
5. Ejecutar MongoDB
sudo service mongod start
6. Se puede verificar que está en marcha viendo si hay actividad en el fichero

/etc/mongod.conf.27017,

y se puede parar el servicio como:

  sudo service mongod stop 

y reiniciarlo como:

  sudo service mongod restart 


2. Instalacion de Robomongo

Este programa nos ayuda en muchas tareas de mantenimiento de MongoDB.

Para ello se descarga desde la web oficial de Robomongo. Para el caso de Ubuntu, se puede hacer lo siguiente:

1. Descargar el fichero (en este caso robomongo-0.9.0-linux-x86_64-0786489.tar.gz)
2. Ejecutar tar xf robomongo-0.9.0-linux-x86_64-0786489.tar.gz
3. Moverlo a /usr/bin/robomongo:
    sudo mv robomongo-0.9.0-linux-x86_64-0786489 /usr/bin/robomongo
4. Instrucciones para instalar elementos en el gnome.desktop:
    sudo apt-get install --no-install-recommends gnome-panel
5. Crear un nuevo acceso directo en el escritorio:
    /usr/bin/gnome-desktop-item-edit /home/<user>/<nombreDesktop>/ --create-new
  DONDE:
  <user>: es el nombre del usuario que utilizamos para entrar en ubuntu.
  <nombreDesktop> es la carpeta que cuelga de /home/<user> que hace referencia al Escritorio.
      Los valores posibles son :Desktop, Escritorio, Escriptori ...... , en mi caso Escriptori
6. Ahora aparecera la siguiente pantalla o parecida,


7. Y quedará el acceso directo creado. Pero si queremos que aparezca en el Launcher, arrastraremos el acceso directo al Launcher y ya está.

8. Ahora ejecutamos desde el lanzador, y aparece esta pantalla. Le damos create:


y aparece esta otra y le damos de nombre local y el resto igual (address : localhost: 27017)





y le damos al test y funciona y luego save.

3. Conceptos básicos  

En MongoDB hay 3 conceptos básicos:

1. Document que es un array de propiedades con sus correspondientes valores. Es equivalente a un registro de una BBDD relacional. Por ejemplo un document es:

  { name: "John", age:21 , isTall: true }

2. Collection que es un conjunto de documentos. Que sería el equivalente de una tabla.

3. Database que es un conjunto de collections. Coincide con una base de datos.


4. Sentencias básicas.

Podemos abrir una sesion de terminal  y ejecutar mongo (que es la utilidad que lleva instalada para manejar mongoDB)



Y podemos ejecutar los comados básicos de manejo de BS y colecciones.


show dbs: Muestra las BDs que temos creadas.
use myDBS: Usa la BD myDBS, si no existe, previamente la crea.
db: muestra la BB en uso.
db.createCollection("myCollection"); : Crea la colección "myCollection".
show collections : muestra las colecciones que tenos en la BD.
db.myCollection.drop(); : Borra la colección myCollection
db.dropDatabase();: Barra la BD.

Las sentencias pueden ser multilinea.


Manejo de documentos:


db.myCollection.insert({name: "Juan" , edad: 23}); : Inserta este documento, o un array de documentos.

db.myCollection.find(expresión_filtro).comando_pipe(); :Hace un filtro basado en la expresión de filtro y arregla la salida con el comando.

  Valores de expresión_filtro:
      {}    No hay restricción de búsqueda
      {name:"Juan"}    Que el name sea "Juan"
      {} , {name:1, _d:0} Muestra solo el nombre de todos los documentos.
      { edad: {$gt: 20}}    Muestra solo aquellos que la edad es mayor de 20
      { name: /a/}    Muestra solo aquellos que el nombre contiene la letra a
      { name: /^Ju/}    Muestra solo aquellos que el nombre comienza por "Ju"
      { edad: {$gt: 20} ,  name:/^Ju/}  Si la edad es mayor de 20 y el nombre comienza por "Ju"

  Valores para el comando_pipe:
     pretty()  La salida es mas arreglada.
     count()  Cuenta los documentos.
     limit(4)  Solo saca 4 resultados
     sort( name: +1 )  La salida esta ordenada ascendientement por nombre. (En -1 es descendiente)
     forEach(function(doc){print("Nombre de la persona: " + doc.name)})  Mostrará "Nombre de la persona:" junto con su nombre para cada registro de la selección.

db.myCollection.update(exp_filtro, exp_set, exp_conjunto) : Actualiza una colección en base a una expresion de filtro exp_filtro, actualizando los campos que se indican en exp_set, y si se hacen todos o no con la expresion exp_mult.

   Los valores de exp_filtro coinciden con el apartado anterior de expresion_filtro.

   Los valores de exp_set:
       { name: "Juan José"}  Cambia el nombre a "Juan José"
       { name: "Juan José", edad: 12}  Cambia el nombre a "Juan José" y edad a 12
 
  Los valores de exp_conjunto:
       { multiline: true }  Cambia todos los registros afectados a la vez.
 
db.myCollection.remove({expresión_filtro); : Elimina los documentos de la colección afectados por la expresion de filtro.


5. Utilización de robomongo.

Permite explorar la BD que hemos creado, y al mismo tiempo ver todos los elemetos que tiene esta base de datos.

También permite ejecutar comandos, y también consultar los comandos disponibles.

Permite ver que comandos se estana ejecutando a medida que exploramos nuestra Bd y csu elementos. Por tanto no hace falta memorizar nada.




miércoles, 4 de enero de 2017

Angular 2. Routing. Entrega 12. Glosario de navegación (3).

Copiamos el glosario de Routing de la documentación oficial de angular2, de la que estamos copiando todo, ya que estoy intentado resumirla y aprender.

Router Part
Meaning
Router Displays the application component for the active URL. Manages navigation from one component to the next.
RouterModule A separate Angular module that provides the necessary service providers and directives for navigating through application views.
Routes Defines an array of Routes, each mapping a URL path to a component.
Route Defines how the router should navigate to a component based on a URL pattern. Most routes consist of a path and a component type.
RouterOutlet The directive () that marks where the router should display a view.
RouterLink The directive for binding a clickable HTML element to a route. Clicking an anchor tag with a routerLink directive that is bound to a string or a link parameters array triggers a navigation.
RouterLinkActive The directive for adding/removing classes from an HTML element when an associated routerLink contained on or inside the element becomes active/inactive.
ActivatedRoute A service that is provided to each route component that contains route specific information such as route parameters, static data, resolve data, global query params and the global fragment.
RouterState The current state of the router including a tree of the currently activated routes together with convenience methods for traversing the route tree.
Link Parameters Array An array that the router interprets as a routing instruction. You can bind that array to a RouterLink or pass the array as an argument to the Router.navigate method
Routing Component An Angular component with a RouterOutlet that displays views based on router navigations.

martes, 3 de enero de 2017

Angular 2. Routing. Entrega 11. Componente de navegacion (2)

En el tutorial de Angular2, se plantea tener un elemento que gestione toda la navegación. Esta navegación puede contener parámetros etc. Para ello se definen las navegaciones posibles en una constante.

Se puede ver el ejemplo oficial en plunker que esta muy bien.


1. Fichero index.html

Hay que colocar en primer lugar despues del <head> de index.html esto:


<base href="/">

2. El fichero del módulo

Este fichero app.module.ts, debe de recoger toda la información de los elementos y componentes utilizados, por tanto es muy importante no dejarse ninguno. En este módulo se deberá:

1. Hacer import de lo básico NgModuleBrowserModuleFormsModule
2. Hacer import de los componentes y servicios que hemos creado, pero también del componente gestor de navegación.
3. Dentro de @NgModule() en los arrays de :
  3.1 imports se incluirá BrowserModule, FormsModule, y AppRoutingModule.
  3.2 declarations se incluirán solo los componentes AppComponent, DashboardComponent,           HeroDetailComponent,  HeroesComponent
  3.3 providers se incluirá el servicio HeroService.
  3.4 bootstrap se incluira AppComponent que es el que arranca la aplicación

Veamos el código de app.module.ts:

import { NgModule }       from '@angular/core';
import { BrowserModule }  from '@angular/platform-browser';
import { FormsModule }    from '@angular/forms';

import { AppComponent }         from './app.component';
import { DashboardComponent }   from './dashboard.component';
import { HeroDetailComponent }  from './hero-detail.component';
import { HeroesComponent }      from './heroes.component';
import { HeroService }          from './hero.service';

import { AppRoutingModule }     from './app-routing.module';

@NgModule({
  imports: [
    BrowserModule,
    FormsModule,
    AppRoutingModule
  ],
  declarations: [
    AppComponent,
    DashboardComponent,
    HeroDetailComponent,
    HeroesComponent
  ],
  providers: [ HeroService ],
  bootstrap: [ AppComponent ]
})
export class AppModule { }

3. Componente que gestiona la navegación

Este componente debe:
1. Tener un import RouterModule y Routes para tener acceso a la navegación.
2. Tener un import a cada componente que se accede con las Routes,
3. Crear una constante tipo Routes que tenga el path a acceder y el componente a utilizar
4. En dicha constante pueden haber rutas con parámetros
4. En la costante Route también debe tener un redirectTo para el path vacío.
5. En imports de @NgModule debe estar RouterModule.forRoot(routes).
6. En exports de @NgModule debe estar RouterModule.

Veamos el ejemplo del código app-routing.module.ts:

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

import { DashboardComponent }   from './dashboard.component';
import { HeroesComponent }      from './heroes.component';
import { HeroDetailComponent }  from './hero-detail.component';

const routes: Routes = [
  { path: '', redirectTo: '/dashboard', pathMatch: 'full' },
  { path: 'dashboard',  component: DashboardComponent },
  { path: 'detail/:id', component: HeroDetailComponent },
  { path: 'heroes',     component: HeroesComponent }
];

@NgModule({
  imports: [ RouterModule.forRoot(routes) ],
  exports: [ RouterModule ]
})
export class AppRoutingModule {}


4. Servicio que obtiene el objeto por el id

Este componente debe:
1. Hacer un import de Injectable, ya que es un servicio.
2. Tener la anotación @Injectable().
3. Tener un método de tipo Promesa<objetoADevolver> que obtenga el objeto con id dado.
Veamos el código del componente del servicio hero.service.ts

import { Hero } from './hero';
import { HEROES } from './mock-heroes';
import { Injectable } from '@angular/core';

@Injectable()
export class HeroService {
  getHeroes(): Promise<Hero[]> {
    return Promise.resolve(HEROES);
  }

  getHeroesSlowly(): Promise<Hero[]> {
    return new Promise(resolve => {
      // Simulate server latency with 2 second delay
      setTimeout(() => resolve(this.getHeroes()), 2000);
    });
  }

  getHero(id: number): Promise<Hero> {
    return this.getHeroes()
               .then(heroes => heroes.find(hero => hero.id === id));
  }
}

5. Componente que recoge los heroes y navega al heroe por id mediante el objeto Router en typescript, con pase de parámetros

Este componente recoge totdos los héroes y cuando se selecciona un héroe, navega al detalle de este héroe, y para ello lo enruta con una dirección mas el parámetro id, que utiliza la ruta de la primera clase: { path: 'detail/:id', component: HeroDetailComponent },

1. Debe hacer import de OnInit y Router, junto a lo Hero y HeroService
2. implementar OnInit.
3. Tener un constructor VACIO que tenga de parámetros un Router i un servicio de obtención del objeto.
4. Tener un método ngOnInt que llame a otro que recoja los héroes.
5. El método que recoge todos los héroes llama al servicio y utiliza su método then, que es el que recoge resultado de una promesa.
6. Un método que asigna la variable selectedHero cuando se clicka en ella.
7. Un método que mande navegar a la ruta con el id seleccionado. Para ello utiliza el método navigate. O sea hará una llamada a
  this.router.navigate(['/detail', this.selectedHero.id]);
y con esto, no le hace falta ni inidcar que el componente a utilizar es el HeroDetail, ni debemos hacer un import a HeroDetail, ya que el componente que gestiona la navegación ya lo sabe.
8. NO se tiene que hacer un import del componente que gestiona la navegación ya que se contempla en el app.module.

Veamos el código de heroes.component.ts

import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';

import { Hero } from './hero';
import { HeroService } from './hero.service';

@Component({
  moduleId: module.id,
  selector: 'my-heroes',
  templateUrl: 'heroes.component.html',
  styleUrls: [ 'heroes.component.css' ]
})
export class HeroesComponent implements OnInit {
  heroes: Hero[];
  selectedHero: Hero;

  constructor(
    private router: Router,
    private heroService: HeroService) { }

  getHeroes(): void {
    this.heroService.getHeroes().then(heroes => this.heroes = heroes);
  }

  ngOnInit(): void {
    this.getHeroes();
  }

  onSelect(hero: Hero): void {
    this.selectedHero = hero;
  }

  gotoDetail(): void {
    this.router.navigate(['/detail', this.selectedHero.id]);
  }
}

6. Componente que navega a otros componentes con <nav> en el template. Pase de parámetros

Este componente es muy sencillo ya que no le hace falta referenciar al componente que gestiona la navegación ya que se declara en el app.module.ts. Y tendrá en el template:

1. Un elemento <nav>
2. Tantos elementos <a routerLink="/rutaPropuesta" .. como enlaces propongamos
3. Si queremos enrutar con un parámetro como el id se puede hacer de 4 maneras, todas ellas equivalentes:
   3.1 <a routerLink="/detail/15" routerLinkActive="active">Heroe 15</a>
     Aquí metemos la ruta a piñón fijo.
   3.2 <a routerLink="/detail/{{i}}" routerLinkActive="active">Heroe {{i}}</a>
         Aquí le pasamos una variable i que tiene el id del héroe
   3.3 <a [routerLink]="['/detail',j]" routerLinkActive="active">Heroe {{j}}</a>
         Aquí le pasamos una variable j que tiene el id del héroe, pero routerlink es un objeto y va entre corchetes
   3.4 <a [routerLink]="['/detail',j, {foo:'kk']" routerLinkActive="active">Heroe {{j}}</a>
         Aquí le pasamos una variable j que tiene el id del héroe, pero también le pasamos un parámetro opcional "foo" que vale "kk", siendo routerlink es un objeto que va entre corchetes
 <a [routerLink]="['/detail', k ,{ foo: 'tatia' }]" routerLinkActive="active">Heroe {{k}}</a>
4. Cerrar el nav  con </nav>
5. Al final incluir <router-outlet></router-outlet>
Veamos su código

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

@Component({
  moduleId: module.id,
  selector: 'my-app',
  template: `
    <h1>{{title}}</h1>
    <nav>
      <a routerLink="/dashboard" routerLinkActive="active">Dashboard</a>
      <a routerLink="/heroes" routerLinkActive="active">Heroes</a>
      <a routerLink="/detail/15" routerLinkActive="active">Heroe 15</a>
      <a routerLink="/detail/{{i}}" routerLinkActive="active">Heroe {{i}}</a>
      <a [routerLink]="['/detail',j]" routerLinkActive="active">Heroe {{j}}</a>
      <a [routerLink]="['/detail', k ,{ foo: 'tatia' }]" routerLinkActive="active">Heroe {{k}}</a>

    </nav>
    <router-outlet></router-outlet>
  `,
  styleUrls: ['app.component.css'],
})
export class AppComponent {
  i=12;
  j=13;
  k=14;
  title = 'Tour of Heroes';
}

7. Componente que se llama con un parámetro en la dirección

En este caso tenemos que recoger el parámetro para saber que héroe recoger. Para ello, este componente debe:

1. Hacer import de ActivatedRoute, ParamsLocation para poder trabajar con rutas, además de Component, OnInit y los componentes que utiliza como el servicio HeroService y el componente Hero que nos da la estructura de hero.
2. También debe incorporar el switchMap de reactive
2. Implementar OnInit.
3. Tener un constructor VACIO que tenga de parámetros un ActivatedRoute, Location (para saber donde estamos en el navegador y poder regresar a la página que lo llamó).  y un servicio de obtención del objeto HeroService.
4. Tener un método ngOnInt que recoja los parámetros de llamada (en este caso el id) y que recoja nuestro registro desde el servicio. Para elo utiliza observables
5. Tener una función para volver a la página anterior:  this.location.back();

Veamos el código de hero-detail.component.ts:

import 'rxjs/add/operator/switchMap';
import { Component, OnInit }      from '@angular/core';
import { ActivatedRoute, Params } from '@angular/router';
import { Location }               from '@angular/common';

import { Hero }         from './hero';
import { HeroService }  from './hero.service';
@Component({
  moduleId: module.id,
  selector: 'my-hero-detail',
  templateUrl: 'hero-detail.component.html',
  styleUrls: [ 'hero-detail.component.css' ]
})
export class HeroDetailComponent implements OnInit {
  hero: Hero;

  constructor(
    private heroService: HeroService,
    private route: ActivatedRoute,
    private location: Location
  ) {}

  ngOnInit(): void {
    this.route.params
      .switchMap((params: Params) => this.heroService.getHero(+params['id']))
      .subscribe(hero => this.hero = hero);
  }

  goBack(): void {
    this.location.back();
  }








Angular 2. Routing. Entrega 10. Navegacion simple(1)

1. Añadir navegación al app.module

Para ello, en app.module.ts:
1. Añadimos  import { RouterModule } from '@angular/router';
2. Creamos una constante que contenga todas las rutas:


const appRoutes: Routes = [
  { path: 'crisis-center', component: CrisisListComponent },
  { path: 'heroes',       component: HeroesComponent } ];
       
3. Indicamos el método RouterModule.forRoot en el imports de @NgModule. Que indica la ruta (path) que asignamos al componente. Se puede asignar la ruta directamente o mejor asignarle la constante anterior.

imports: [

              RouterModule.forRoot([
      {path: 'heroes',component: HeroesComponent}
    ])
],
....
o mucho mejor
@NgModule({
  imports: [
    RouterModule.forRoot(appRoutes)
    // other imports here
  ],
  ...
})
export class AppModule { }

4. Añadir  <a routerLink="/heroes">Heroes</a>  en el template dentro de un <nav>.
5. Añadir  <router-outlet></router-outlet> al final del template.
template: `
  <h1>Angular Router</h1>
  <nav>
    <a routerLink="/crisis-center" routerLinkActive="active">Crisis Center</a>
    <a routerLink="/heroes" routerLinkActive="active">Heroes</a>
  </nav>
  <router-outlet></router-outlet>
`

2. Añadir mas componentes

Para ello se añadirán mas elementos al array del método RouterModule.forRoot en el imports de @NgModule. ( o mejor en la constante appRoutes)


               RouterModule.forRoot([
      {path: 'heroes',component: HeroesComponent},
      {path: 'otro',component: OtroComponent}

    ])
También se añadirá otro <a routerLink="/otro">Heroes</a>  en el template dentro del <nav>. Quedando el template:
template: `
   <h1>{{title}}</h1>
   <nav>
     <a routerLink="/heroes">Heroes</a>
     <a routerLink="/otro">Otro</a>
   </nav>
   <router-outlet></router-outlet>
 `

3. Redirect to

Para ello se añadirán otro elementos al array del método RouterModule.forRoot en el imports de @NgModule, que haga referencia al redirect ( o mejor en la constante appRoutes)

               RouterModule.forRoot([
      {path: 'heroes',component: HeroesComponent},
      {path: 'otro',component: OtroComponent},
      {path: '',redirectTo:'/dashboard', pathMatch: 'full'}
    ])

4. Navegación con parámetro (NO)

Para ello se añadirán otro elementos al array del método RouterModule.forRoot en  el imports de @NgModule, que haga referencia a una ruta al que se le añade "/:parametro"

  { path: 'detail/:id' , component: HeroDetailComponent }

En este caso le pasamos el id como parámetro a la ruta.

Pero en el componente se debe hacer estos import
// Keep the Input import for now, we'll remove it later:
import { Component, Input, OnInit } from '@angular/core';
import { ActivatedRoute, Params }   from '@angular/router';
import { Location }                 from '@angular/common';
Y además se debe importar el servicio que nos proporciona el Hero a partir del id.

Pero entonces la cosa se complica y para ello se va a utilizar una nueva estrategia en el punto siguiente.

Angular 2. Formularios. Entrega 9: Templates (8). Template expression operators. Operador safe navigation

Se utiliza este operador ( ? )para evitar hacer referencias a variables que son nulas o que tienen alguna propiedad nula, sin producir la ruptura del programa

Veamos un ejemplo
The current hero's name is {{currentHero?.firstName}}




lunes, 2 de enero de 2017

Angular 2. Formularios. Entrega 8: Templates (7). Template expression operators. Operador pipe

Las template expressions utilizan un subconjunto de la sintaxis de JavaScript con unos pocos operadores para escenarios específicos. Solamente explicaramos 2 operadores el pipe y el safe navegation. En esta entrada solo hablaremos del pipe.

1. El operador pipe (|). Introducción

Al igual que se hace en unix, el operador pipe realiza transformaciones ya sea para filtrar, ordenar, convertir a mayúscula etc.

Veamos las utilidades que tiene de serie:

1. Convertir a mayúscula {{title | uppercase}}
2. Convertir a minúscula {{title | lowercase}}
3. Encadenamiento de conversiones {{title | uppercase | lowercase}}
4. Dar formato como fecha {{currentHero?.birthdate | date}}
5. Aplicar parámetros {{currentHero?.birthdate | date:'longDate'}}
6. Transformar a json (depuración) {{currentHero | json}}
7. Dar formato de moneda {{importe | currency}}
8. Dar formato de porcentaje {{porcentajePerdidas | percent}}
9. Dar formato a un número {{potencia | number}}
10. Devolver el último valor de un obsevable o promesa  {{promesa$ | async}}
11. Internacionalización {{numero | i18nPlural:mapping}} ver mas abajo.
12. Recorte de string o array   {{miString | slice:comienzo[:fin]}}

NOTA: Los pipes de fecha (date) y moneda (currency) necesitan la ECMAScript Internationalization API. Safary y otros navegadores antiguos no la sportan. Se puede añadir un polyfill  en el template.

<script src="https://cdn.polyfill.io/v2/polyfill.min.js?features=Intl.~locale.en"></script>

2. Parámetros de algunos pipes predefinidos

Algunos pipes predefinitos admiten porcentajes:
1. number[:digitInfo]   teniendo digitInfo este formato;
     {minIntegerDigits}.{minFractionDigits}-{maxFractionDigits}
2. percent[:digitInfo] teniendo digitInfo el mismo formato anterior
3. currency[:currencyCode[:symbolDisplay[:digitInfo]]] donde
  currencyCode cumple el ISO 4217 (USD para el dolar y EUR para el euro)
  digitInfo es igual que en apartados anteriorresal anterior y
  symbolDisplay es booleano e indica si se muestra el símbolo de la moneda o no

3. date[:format] donde el formato puede ser:
  3.1 'medium' (yMMMdjms) , 'short' (yMdjm): Para indicar fecha y hora
  3.2 'fullDate' (yMMMMEEEEd), 'longDate' (yMMMMd), 'mediumDate'(yMMMd),
         'shortDate'(yMd): para inidicar fechas
  3.3 'mediumTime'(jms) y 'shortTime'(jm): Para indicar horas

  Además se contemplan los siguientes símbolos:
  3.4 : G (era), y (year), M (month), d (day), E (weekday),
  3.5:  j (hour), h (hour12), H (hour24), m (minute), s (second)
  3.6: z (timezone), Z (timezone), a (timezone)

Veamos un ejemplo con fechas:
<p>Today is {{today | date}}</p
<p>Or if you prefer, {{today | date:'fullDate'}}</p>
<p>The time is {{today | date:'jmZ'}}</p>

4. i18nPlural:mapping debiendo cumplir mapping el formato ICU.
5. islice:comienzo[:fin]

3. Parámetros con expresiones

Pero estos parámetros a parte de poder admintir constantes (numericas de string etc), tambien adminten template expressions.

Veamos un ejemplo donde cambiamos la variable miFormato de shortDate a fullDate.
En el template:
 <p>The hero's birthday is {{ birthday | date:miFormato }}</p>
  <button (click)="toggleFormat()">Toggle Format</button>
En el componente:
export class HeroBirthday2Component {
  birthday = new Date(1988, 3, 15); // April 15, 1988
  toggle = true; // start with true == shortDate

  get miFormato()   { return this.toggle ? 'shortDate' : 'fullDate'; }
  toggleFormat() { this.toggle = !this.toggle; }
}


4. Creación de pipes a medida

Para ello tenemos que:
1. Utilizar la anotación @Pipe ({name: 'miPipe'}) a la que pasamos el nombre miPipe 
2. Realizar la importación en el import de  Pipe y PipeTransform
3. Debemos incluir nuestro pipe en declarations del AppModule.
4. La clase pipe debe implementar el método transform el interface PipeTransform que admite valores de entrada y otros valores opcionales y devuelve el valor transformado.

Veamos un ejemplo que damos de nombre al pipe exponentialStrength, al que le pasamos 2 números, y el primer número lo elevamos al segundo, El segundo número es opcional.
Vemos el pipe (app/exponentual.strength.pipe.ts)
import { Pipe, PipeTransform } from '@angular/core';
/*
 * Raise the value exponentially
 * Takes an exponent argument that defaults to 1.
 * Usage:
 *   value | exponentialStrength:exponent
 * Example:
 *   {{ 2 |  exponentialStrength:10}}
 *   formats to: 1024
*/
@Pipe({name: 'exponentialStrength'})
export class ExponentialStrengthPipe implements PipeTransform {
  transform(value: number, exponent: string): number {
    let exp = parseFloat(exponent);
    return Math.pow(value, isNaN(exp) ? 1 : exp);
  }
}
Veamos el template (2 es el primer parámetro y 10 el segundo)
<h2>Power Booster</h2>
<p>Super power boost: {{2 | exponentialStrength: 10}}</p>
También se pueden utilizar template expressions en el template tal como vimos anteriormente.

Hay que tener cuidado con las actualizaciones del contenido de un array. Angular tiene una referencia a un array al que podemos aplicarle un pipe. Si añadimos elementos al array, la referencia al array no cambia, por tanto, no actualiza la pantalla. Si queremos que cambie, se tiene que cambiar la referencia a un nuevo array. (En C, Java,.. y la mayoria de lenguajes, se guarda la referencia o posicion de memoria del array u objeto, sin importarnos en primera instancia el contenido del mismo)


5. Pipes puros e impuros

Un pipe impuro permite detectar el cambio del contenido de un array u objeto. Pero tiene la desventaja que consume muchos mas recursos del sistema para ir testeando el componente.

Para inidicar que un pipe es impuro, solamente hay que indicar pure: false en fla anotación
@Pipe({
  name: 'flyingHeroesImpure',
  pure: false
})

6. El pipe AsincPipe

Es un pipe que es impuro que se aplica a una promesa o observable, devolviendo los valores que se emiten. Es stateful, ya que nos reporta los valores del observable a medida que nos llegan.

Veamos un ejemplo de un compopnente

  1. import { Component } from '@angular/core';
  2. import { Observable } from 'rxjs/Observable';
  3. import './rxjs-extensions';
  4. @Component({
  5. selector: 'hero-message',
  6. template: `
  7. <h2>Async Hero Message and AsyncPipe</h2>
  8. <p>Message: {{ message$ | async }}</p>
  9. <button (click)="resend()">Resend</button>`,
  10. })
  11. export class HeroAsyncMessageComponent {
  12. message$: Observable<string>;
  13. private messages = [
  14. 'You are my hero!',
  15. 'You are the best hero!',
  16. 'Will you be my hero?'
  17. ];
  18. constructor() { this.resend(); }
  19. resend() {
  20. this.message$ = Observable.interval(500) // cada 500 mseg emite un entero
  21. // comenzando por 0 e incrementando en 1
  22. // o sea 0,1,2,3,4,5,6....
  23. .map(i => this.messages[i]) //asignamos el mensaje i-esimo
  24. .take(this.messages.length); // paramos pasada la longitud del vector
  25. }
  26. }

7. Filter & Sort

Angular ya no suministra pipes para filtrar y ordenar ya que bajan el rendimiento. Para ello cada cual debe proporcionar estas herramientas desde el componente.