24 - Router : rutas anidadas

En un comienzo trabajamos el desarrollo de aplicaciones Angular componiendo la misma como un conjunto de componentes todas en la misma ruta, por ejemplo:

https://www.sitio.com/

Luego vimos que cuando la aplicación comienza a ser más compleja es más conveniente agrupar sus funcionalidades en distintas rutas, con o sin parámetros:

https://www.sitio.com/inicio
https://www.sitio.com/clientes
https://www.sitio.com/contacto
https://www.sitio.com/articulos

Esta forma de organizar las rutas nos permite crear un sitio más grande, pero ahora veremos que podemos crear rutas anidadas, por ejemplo:

https://www.sitio.com/inicio
https://www.sitio.com/clientes/mayoristas
https://www.sitio.com/clientes/minoristas

Veremos que Angular requiere una sintaxis específica cuando definimos el arreglo Routes para indicar que se trata de una ruta anidada.

Problema

Confeccionar una aplicación que muestre una barra de navegación con 2 rutas: 'America' y 'Europa'.
Cuando se selecciona 'America', mostrar el mapa de 'América' y una barra de navegación con 3 paises americanos, hacer lo mismo si se elije Europa, emplear rutas anidadas para cada país, de tal forma que se acceda a cada país con la siguiente sintaxis:

https://www.sitio.com
https://www.sitio.com/america
https://www.sitio.com/america/chile
https://www.sitio.com/america/argentina
https://www.sitio.com/america/uruguay
https://www.sitio.com/europa
https://www.sitio.com/europa/espana
https://www.sitio.com/europa/francia
https://www.sitio.com/europa/italia
  • Crearemos primero el proyecto:

    ng new proyecto019
    
  • Crearemos 2 componentes para cada continente y 6 componentes más para cada país (si copiamos y pegamos en la consola de VSCode podemos rápidamente crear las 8 componentes):

    ng generate component america
    ng generate component america/chile
    ng generate component america/argentina
    ng generate component america/uruguay
    ng generate component europa
    ng generate component europa/espana
    ng generate component europa/francia
    ng generate component europa/italia
    

    Podíamos crear todas las componentes en la misma altura y no crear subcarpetas para cada país, pero queda mucho más ordenada nuestra aplicación si comenzamos a agrupar las componentes en distintas carpetas y subcarpetas en forma jerárquica. Angular CLI crea automáticamente una subcarpeta cuando no existe al utilizar la sintaxis:

    ng generate component america/chile
    

    Se crea la carpeta 'america' y dentro de la misma se guardan los cuatro archivos asociados a la componente 'chile'.

    Podemos ver en el editor de texto las 8 componentes creadas:

    Router rutas anidadas angular

    El caracter 'ñ' no se puede utilizar como selector: Selector (app-españa) is invalid.

  • Procedemos a modificar el archivo 'app.routes.ts' definiendo las rutas principales y las anidadas:

    import { Routes } from '@angular/router';
    import { AmericaComponent } from './america/america.component';
    import { ChileComponent } from './america/chile/chile.component';
    import { ArgentinaComponent } from './america/argentina/argentina.component';
    import { UruguayComponent } from './america/uruguay/uruguay.component';
    import { EuropaComponent } from './europa/europa.component';
    import { EspanaComponent } from './europa/espana/espana.component';
    import { FranciaComponent } from './europa/francia/francia.component';
    import { ItaliaComponent } from './europa/italia/italia.component';
    export const routes: Routes = [
      {
        path: 'america',
        component: AmericaComponent,
        children: [
          {
            path: 'chile',
            component: ChileComponent
          },
          {
            path: 'argentina',
            component: ArgentinaComponent
          },
          {
            path: 'uruguay',
            component: UruguayComponent
          }
        ]
      },
      {
        path: 'europa',
        component: EuropaComponent,
        children: [
          {
            path: 'espana',
            component: EspanaComponent
          },
          {
            path: 'francia',
            component: FranciaComponent
          },
          {
            path: 'italia',
            component: ItaliaComponent
          }
        ]
      }
    ];
    

    Agregamos en cada objeto que tiene rutas anidadas la propiedad 'children', la cual es un arreglo de objetos donde definimos todas las rutas anidadas.

    Luego podemos indicar en el navegador una ruta principal:

    https://www.sitio.com/america
    

    Pero también podemos acceder a una ruta anidada con la sintaxis:

    https://www.sitio.com/america/chile
    
  • Procedemos a modificar la componente principal que nos genera Angular 'app.component.html':

    <div class="menu">
      <a routerLink="america">America</a>
      <a routerLink="europa">Europa</a>
    </div>
    
    <div>
      <router-outlet />
    </div>
    

    La directiva 'router-outlet' es indispensable para que se muestren alguna de las dos componentes 'AmericaComponent' o 'EuropaComponent' según que enlace se seleccione.

    También modificamos el archivo app.component.ts:

    import { Component } from '@angular/core';
    import { RouterOutlet, RouterLink } from '@angular/router';
    
    @Component({
      selector: 'app-root',
      imports: [RouterOutlet, RouterLink],
      templateUrl: './app.component.html',
      styleUrl: './app.component.css'
    })
    export class AppComponent {
      title = 'proyecto019';
    }
    
  • Cuando se selecciona la ruta 'america' se carga la componentes 'AmericaComponent', modificamos la vista de dicha componente 'america.component.html'

    <iframe
      src="https://www.google.com/maps/embed?pb=!1m14!1m12!1m3!1d31536306.714862086!2d-54.01447990393665!3d-20.38062741924525!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!5e0!3m2!1ses!2sar!4v1583676893900!5m2!1ses!2sar"
      width="600" height="450" frameborder="0" style="border:0;" allowfullscreen=""></iframe>
    <div class="menu">
      <a routerLink="chile">Chile</a>
      <a routerLink="argentina">Argentina</a>
      <a routerLink="uruguay">Uruguay</a>
    </div>
    <router-outlet />
    

    Disponemos tres enlaces hacia las rutas anidadas, recordemos que esta componente se activa cuando se seleccionó la ruta 'america'.

    También esta componente dispone la etiqueta 'router-outlet' donde deben visualizarse las componentes 'ArgentinaComponent', 'ChileComponent' o 'UruguayComponent'.

  • También debemos modificar el archivo 'america.component.ts' agregando los import respectivos

    import { Component } from '@angular/core';
    import { RouterOutlet, RouterLink } from '@angular/router';
    @Component({
      selector: 'app-america',
      imports: [RouterOutlet, RouterLink],
      templateUrl: './america.component.html',
      styleUrl: './america.component.css'
    })
    export class AmericaComponent {
    
    }
    
  • Exactamente lo mismo hacemos para crear la componente 'europa.component.html':

    <iframe src="https://www.google.com/maps/embed?pb=!1m14!1m12!1m3!1d9880418.608500127!2d2.640727530399596!3d45.69187171781666!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!5e0!3m2!1ses!2sar!4v1583677509059!5m2!1ses!2sar" width="600" height="450" frameborder="0" style="border:0;" allowfullscreen=""></iframe>
    <div class="menu">
      <a routerLink="espana">España</a>
      <a routerLink="francia">Francia</a>
      <a routerLink="italia">Italia</a>
    </div>
    <router-outlet />
    
  • También debemos modificar el archivo 'europa.component.ts' agregando los import respectivos

    import { Component } from '@angular/core';
    import { RouterOutlet, RouterLink } from '@angular/router';
    
    @Component({
      selector: 'app-europa',
      imports: [RouterOutlet, RouterLink],
      templateUrl: './europa.component.html',
      styleUrl: './europa.component.css'
    })
    export class EuropaComponent {
    
    }
    
  • Ya tenemos prácticamente finalizado el ejemplo de rutas anidadas con Angular, podemos modificar las vistas de las componentes de cada país:

    chile.component.html
    argentina.component.html
    uruguay.component.html
    espana.component.html
    francia.component.html
    italia.component.html
    
  • Vamos a disponer una serie de estilos comunes a todos los menúes de la aplicación, para ello modificamos el archivo 'styles.css' que se encuentra en la raiz del proyecto:

    /* You can add global styles to this file, and also import other style files */
    
    .menu {
      display: flex;
      justify-content: space-around;
      background-color: #333;
      padding: 10px;
    }
    
    .menu a {
      color: #fff;
      text-decoration: none;
      padding: 5px 10px;
    }
    
    .menu a:hover {
      background-color: #555;
    }
    

Si seleccionamos la opción de América:

Router rutas anidadas angular

Finalmente si ingresamos a una ruta anidada por ejemplo Argentina:

Router rutas anidadas angular

Podemos probar esta aplicación en la web aquí.