paso2 old - keblato/TutorialesTalleres-Angular GitHub Wiki

Paso 2

Checkout del paso 2

Comience por realizar el checkout del paso-1b del front. Si no encuentra la rama del paso1b significa que cuando clonó el proyecto no clonó esta rama, en ese caso por favor clone la rama.

git checkout -f paso-1b

Actualice, preferiblemente en una ventana de comandos, la instalación de paquetes con:

npm install

Requerimientos de ver el detalle de un elemento

En este ejemplo queremos que cuando un usuario seleccione (dando clic) un libro, un autor o una editorial se muestre el detalle de ese elemento.

También queremos que, en cada caso, se muestre la lista de libros que corresponda, así:

  • Se se pide el detalle de un autor se muestra la lista de imágenes de los libros escritos por ese autor
  • Si se pide el detalle de un libro se muestra la lista de imágenes de los demás libros
  • Si se pide el detalle de una editorial se muestra la lista de imágenes de los libros editados por esa editorial.

Las siguientes imágenes muestran este resultado

book2-detalleautor
Figura 1: el detalle de un autor
book2-detallelibro
Figura 2: el detalle de un libro
book2-detalleeditorial
Figura 3: el detalle de una editorial

Diseño

Para esta solución, cada módulo AuthorModule, BookModule, EditorialModule van a tener un nuevo componente para el detalle del elemento, correspondientemente: AuthorDetailComponent, BookDetailComponent y EditorialDetailComponent.

El componente compartido

Podrá darse cuenta que el html del componente BookListComponent ha cambiado:

book2-booklistcomponent
Figura 4: book-list.component.html

Esto se debe a que un nuevo componente genérico para mostrar una lista de libros cualquiera fue creado (book-sidebar).

Este componente se encuentra en el nuevo módulo de componentes compartidos (SharedModule).

book2-sharedstructure
Figura 5: el módulo SharedModule

¿Cómo funciona un componente compartido?

Para poder utilizar un componente que hace parte de otro módulo, el módulo del componente padre debe importar el módulo que contiene el componente hijo.

Esto quiere decir que deberá importar el módulo SharedModule en los demás módulos (incluyendo el AppModule) para que los demás componentes puedan usarlo.

book2-sharedstructure
Figura 6: BookModule importa SharedModule

Una vez importado el módulo, basta con hacer uso de la directiva del componente compartido para incluirlo en cualquier otro componente.

¿Cómo pasar parámetros al componente compartido?

En esta nueva iteración, el componente compartido es utilizado 4 veces:

  • En el BookListComponent (la lista de todos los libros del paso 1)
  • En el BookDetailComponent (nuevo componente)
  • En el AuthorDetailComponent (nuevo componente)
  • En el EditorialDetailComponent (nuevo componente)

Sin embargo, la ventaja del componente compartido es que no se debe agregar una lista diferente en cada uno de esos componentes, sino que se puede utilizar la lista genérica y pasarle por parámetro los libros a mostrar.

Esto se logra así:

  1. La lista de libros en el componente compartido es de tipo @Input
book2-input
Figura 7: el parámetro Books en el componente compartido
  1. El componente padre se encarga de pedir los libros que necesita, y se los pasa por parámetro al componente compartido.

Por ejemplo, el BookListComponent pide todos los libros al BookService y los guarda en la variable books.

book2-booklistcomponentts
Figura 8: book-list.component.ts

En el HTML, en el tag de la directiva del componente compartido, entre [] se escribe el nombre del @Input y se define que sea igual que la variable que contiene los libros:

<app-book-sidebar [books]="books"></app-book-sidebar>

book2-booklistcomponent
Figura 9: book-list.component.html

Los nuevos componentes

Los nuevos componentes fueron creados a través del CLI de Angular con los comandos:

ng generate component nombre-del-nuevo-componente

Detalles de un libro

La nueva ruta

Para mostrar los detalles de un libro, se agregó una nueva ruta al router.

book2-bookdetailroute
Figura 10: nueva ruta para ver los detalles de un libro

En ella se especifica que:

  • La ruta "/books/:id" es atendida por el BookDetailComponent

Para obligar que en una misma URL siempre se vuelva a cargar el componente, se debe hacer una especificación al RouterModule:

{onSameUrlNavigation: 'reload'}

book2-onsameroute
Figura 11: especificación en el router para forzar que el componente sea cargado cada vez que se accede a la URL

Sin esta especificación, si por ejemplo, usted hiciera click en uno de los "Otros libros" en la sección inferior de los detalle de un libro, la visualización no cambiaría. Esto porque por defecto, el componente no volvería a inicializarse y esto es necesario para que busque los detalles del nuevo libro.

El nuevo componente

Este componente presenta varios cambios con respecto a los componentes que fueron implementados en el paso 1.

Fíjese en la definición del componente y en su constructor:

book2-bookdetailconstructor
Figura 12: constructor del book-detail.component.ts

Se pueden observar 3 nuevos elementos o cambios con respecto a lo que se había hecho en el paso 1:

  1. El componente implemente OnDestroy.
  2. Dos nuevos parámetros para el constructor (la ruta de tipo ActivatedRoute y el router router de tipo Router)
  3. Una suscripción de navegación (navigationSubscription) que permite conocer cuándo se debe refrescar el componente.

Esta suscripción es destruida cuando hay un cambio de controlador a través del método ngOnDestoy.

book2-oninitondestroy
Figura 13: ngOnInit() y ngOnDestroy() book-detail.component.ts

El método ngOnInit también es más complejo que en los casos anteriores:

  • A través de +this.route.snapshot.paramMap.get('id'); se obtiene el id del libro que está en la URL.
  • Una vez identificado el id, éste se guarda en la variable book_id. La función getBook() lo utiliza para pasarlo por parámetro al servicio.
  • La función getAllBooks() trae todos los libros y los guarda en la variable other_books. De esa lista se elimina el libro cuyos detalles se están mostrando, y se pasa por parámetro al BookSidebarComponent (el componente compartido).
book2-bookdetailconstructor
Figura 14: funciones getBook() y getAllBooks()

Los componentes EditorialDetailComponent y AuthorDetailComponent funcionan de la misma manera.

Obtienen el id del autor o de la editorial de la ruta, y utilizan los servicios correspondientes para obtener los detalles y los libros a mostrar en el componente compartido (los libros publicados por el autor, o los libros publicados por la editorial).