viernes, 19 de mayo de 2017

Angular 2 y C3.css (3): Definición de componentes visuales primarios

Introducción

Queremos crear 3 componentes:

1. Componente principal AppComponent que es el contenedor de todo con el boton "hamberger" que oculta y muestra el menu lateral
2. Menu Lateral Izquierdo (Sidebar): SidebarComponent
3. Caja de contenidos en la parte derecha:ContentComponent

1. AppComponent

Veamos el código type script (app.component.ts)

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

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

export class AppComponent {
  title = 'app works!';
  sbVisible = false; // whether sidebar menu is visible or not

  // Hide or show sidebar
  hideSBOnOff(): void {
    this.sbVisible = !this.sbVisible;
  }
}

De este código destacamos:

1. La variable sbVisible que es la que indoca si el menú de la barra lateral esta visible (display:in-line) o si está oculto (display:none).

2. La función hideSBOnOff() lo que hace es cambiar el valor de sbVisible



Vemos el código html (app.component.html)

<div class="w3-main" id="main">

  <div class="w3-row w3-teal w3-border" id ="main-row">
    <div class="w3-container w3-col" style="width:100px">
      <button class="w3-button w3-xxlarge" (click)="hideSBOnOff()">&#9776;</button>
    </div>
    <div class="w3-container w3-rest">
      <h1>My Application</h1> 
    </div>
  </div><!--  end main-row-->
  

  <!--  Left for sidebar -->
  <app-sidebar [visible]="sbVisible"></app-sidebar>

  <!--  Right for content -->
  <app-content [sBarVisible]="sbVisible"></app-content>

</div> <!-- end main -->

De este código destacamos:

1. La creación de caracter "hamberguer" con &#9776;

2. Como llamamos a la función hideSBOnOff() al hacer click del boton: (click)="hideSBOnOff()"

3. Como insertamos los componentes AppSidebar y AppContent con las directivas <app-sidebar> y <app-content>

4. Como pasamos la variable sbVisible a cada componente, dentro de sus directivas correspondientes. Para ello, cada componente debe tener un atributo con la anotacion @Input que para el AppSidebar será el atributo "visible" y para el AppContent será "sBarVisible". Los atributos de cada componente iran entre corchetes [].

2. SidebarComponent

El código typescript es (sidebar.component.ts)

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

@Component({
  selector: 'app-sidebar',
  templateUrl: './sidebar.component.html',
  styleUrls: ['./sidebar.component.css']
})

export class SidebarComponent implements OnInit {
  // whether is visible or not this component
  @Input() visible: boolean; // receives input from parent

  constructor() { }

  ngOnInit() {
  }

 // Gets the style and show or hide this sidebar
 getSideBarStyle() {
    const SideBarStyle = {
       'width': '25%',
       'display': this.visible ? 'inline-block' : 'none',
    };
    return SideBarStyle;
  }
}

Destacamos:

1. selector: 'app-sidebar' que es la directiva que utiliza el componente padre (appComponent) para incrustar este componente dentro del html del componente padre.

2. @Input() visible que es el atributo que le pasa el componente padre para que esté visible o no.

3. getSideBarStyle(): Que es la función que nos devuelve el estilo en función de si es visible o no. También nos da la anchura.

Veamos el codigo html (sidebar.component.html)

<div class="w3-sidebar w3-bar-block w3-card-2 w3-animate-left"  [ngStyle]="getSideBarStyle()" id="mySidebar">
  <!-- button class="w3-bar-item w3-button w3-large" (click)="hideOnOff()">Close &times;</button -->
  <a href="#" class="w3-bar-item w3-button">Link 1</a>
  <a href="#" class="w3-bar-item w3-button">Link 2</a>
  <a href="#" class="w3-bar-item w3-button">Link 3</a>

</div>


Destacamos como con la notación [ngStyle]="getSideBarStyle()" le asignamos el valor del estilo para que sea visible (display:in-line) o no (display:none).



3. ContentComponent

Veamos el código typescript:

import { Component, OnInit, Input, Output } from '@angular/core';

@Component({
  selector: 'app-content',
  templateUrl: './content.component.html',
  styleUrls: ['./content.component.css']
})
export class ContentComponent implements OnInit {
  @Input() sBarVisible: boolean; // <-- added Input annotation

  constructor() {
    this.sBarVisibleEmitter = new EventEmitter();
  }

  ngOnInit() {
  }

  // gets this componet style
  getContentStyle() {
    const mainStyle = {
       'margin-left': this.sBarVisible ? '25%' : '0%',
    };
    return mainStyle;
  }
}


Destacar:
1. selector: 'app-content' que es la directiva que usa el componente padre en el html para incluirlo
2. @Input sBarVisible que es la variable que le pasa el componente padre para decirle que la barra lateral esta visible o no para que este componente se readapte
3. getContentStyle() que es la función que cambia el estilo para que se comparta el contenido total con el menu lateral. Es este caso cuando la barra lateral es visible le damos un margen izquierdo del 25%

Veamos el html (content.component.html)

<div class="w3-tile" [ngStyle]="getContentStyle()" id="content">

  <img src="../assets/images/img_car.jpg" alt="Car" style="width:100%">

  <div class="w3-container">
    <p>In this example, the sidebar is hidden (style="display:none")</p>
    <p>It is shown when you click on the menu icon in the top left corner.</p>
    <p>When it is opened, it shifts the page content to the right.</p>
    <p>We use JavaScript to add a 25% left margin to the div element with id="main" when this happens. The value "25%" matches the width of the sidebar.</p>
  </div>

</div>

A destacar:

1. La aplicación de estilos con la directiva ngStyle: [ngStyle]="getContentStyle()" que utiliza la función getContentStyle del componente.

2. El resto de contenido es copiado de la web de w3schools. Observar que la foto del coche se ha puesto en el directorio assets/images

Pero no debemos olvidar el app.module.ts que es el que nos une todos los componentes:

3. AppModule.ts

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

import { AppComponent } from './app.component';
import { SidebarComponent } from './my_ui/sidebar/sidebar.component';
import { ContentComponent } from './my_ui/content/content.component';

@NgModule({
  declarations: [
    AppComponent,
    SidebarComponent,
    ContentComponent
  ],
  imports: [
    BrowserModule,
    FormsModule,
    HttpModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

Observar que cada componente lo crea en una carpeta nueva. Y también he creado la carpeta my_ui para saber tener todo junto esta parte de interfaz de usuario (my_ui)

Si ejecutamos queda esto:

Y si mostramos el menu lateral dandole al boton hamberguer:




4. Conclusiones

De momento no hemos utilizado el modelado de datos. En esta tercera entrega solo hemos comprobado que los componentes hacen lo que queremos.

Angular 2 y C3.css (2): Definición del modelo de datos

Introducción

Primeramente vamos a definir el modelado de los elementos de la interfaz de usuario

1. Modelo de datos

En principio crearemos varios ficheros: 
  • config.model.ts: donde guardaremos parámetros y enumeraciones
  • menu.model.ts: que define la estructura de menú
Veamos el primero (config.model.ts):

/**
 * Configuration and base enums
 */

/**
 * Type of action in a menu
 */
export enum MenuAction {
    Menu = 0,    // Link to submenu
    Component,   // Link to a component
    Procedure,   // Link to a procedure
    URL          // link to an URL
}


Y ahora el segundo (menu.model.ts)

/**
 * Menu structure
 */
import { MenuAction } from './config.model'; // <-- import this

export class Menu {
  title: string;            // title of the menu
  actionType: MenuAction;   // Type of action as MenuAction
  action: string;           // action
  submenu: Menu;            // submenu
  info: string;             // Additional info

  constructor(title: string, actionType: MenuAction,
              info: string, action: string, submenu: Menu) {
  this.title = title;
  this.actionType = actionType;
  this.info = info;
  this.action = action ;
  this.submenu = submenu;
  }
}





jueves, 18 de mayo de 2017

Angular 2 y C3.css (1): Perspectiva inicial

1. Introducción


Vamos a crear una pequeña aplicación con Angular 2 y C3.css

La decisión de usar C3,css es:
  1. No tiene javascript, por tanto no deberíamos tener problemas con Angular2
  2. Es muy potente
  3. Es muy pequeña
  4. Y sobre todo porque es "responsive" y "mobile first"
Yo estoy utilizando Eclipse con Webclipse.

2. Creación del proyecto

Veamos los pasos que he hecho:

1. He creado un proyecto Angular 2
2. He descargado C3.css a la carpeta app/assets
3. En src/styles.css he puesto la ruta a C3.css


@import './assets/w3.css';

3. Diseño de la interfaz de usuario

Queremos tener un diseño parecido a este de W3Schools . No quiero redescubrir la rueda y utilizar recursos libres que parece que estan funcionando bien.



Para ello adaptamos a este diseño

+-------------------------------------------------+
| ☰              TITULO                          |
+------------+------------------------------------+
|            |                                    | 
| MENU       | ZONA DE CONTENIDO                  | 
| LATERAL    |                                    | 
| OCULTABLE  |                                    | 
|            |                                    | 
|            |                                    | 
+------------+------------------------------------+


Como vemos, queremos un panel lateral que se puede ocultar y mostrar que va a ser nuestro menú, y un panel de contenidos.

Ahora nos queda adaptar lo que nos da W3 al modo de actuar de Angular 2.

Para ello definiremos los siguientes elementos

1. Estructura de datos que guarde el menú (tipo árbol)
2. Componente del menú lateral (sidebar)
3. Componente del contenido principal
4. Servicio simple que proporcione la estructura de datos del menú lateral

De momento, para esta introducción ya tenemos demasiado. Mas adelante lo podemos complicar añadiendo mas components, barras de estado etc.

4. Estructura de datos del menú

Crearemos 2 ficheros 
  • config.model.ts: donde guardaremos parámetros y enumeraciones
  • menu.model.ts: que define la estructura de menú
Veamos el primero:

/**
 * Configuration and base enums
 */

/**
 * Type of action in a menu
 */
export enum MenuAction {
    Menu = 0,    // Link to submenu
    Component,   // Link to a component
    Procedure,   // Link to a procedure
    URL          // link to an URL
}


Y ahora el segundo

/**
 * Menu structure
 */
import { MenuAction } from './config.model'; // <-- import this

export class Menu {
  title: string;            // title of the menu
  actionType: MenuAction;   // Type of action as MenuAction
  action: string;           // action
  submenu: Menu;            // submenu
  info: string;             // Additional info

  constructor(title: string, actionType: MenuAction,
              info: string, action: string, submenu: Menu) {
  this.title = title;
  this.actionType = actionType;
  this.info = info;
  this.action = action ;
  this.submenu = submenu;
  }
}




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();
  }