Routing en Angular: Guía completa: Parte 3

Última actualización: 17 octubre, 2020

Ya hemos visto cómo registrar y cargar rutas para mostrar varias páginas usando únicamente un archivo HTML en lugar de varios, gracias a la magia del Router que forma parte de Angular. También vimos cómo navegar usando rutas relativas (en inglés, relative paths) y absolutas (en inglés, absolute paths) y cómo aplicarles parámetros para crear rutas dinámicas. Continuemos por ese camino. 😉

Cómo obtener parámetros de una ruta

Vamos a simular que alguien quiere acceder a la información de usuario "Jamie" (uno de los users que hemos escrito en el código TypeScript estáticamente). Primero, vamos a escribir manualmente la ruta que queremos simular. Por ejemplo http://localhost:4200/users/1/jamie.

Para ello, lo que haremos será cargar el UserComponent. Una vez cargado, la URL contendrá datos a los que queremos acceder para poder mostrar efectivamente el UserComponent con los parámetros que le hayamos pedidoEs decir, en lugar de mostrar:

User with ID _ID_ loaded.

User name is _NAME_

que se muestre:

User with ID 1 loaded.

User name is Jamie

Obtendremos el acceso desde el archivo TypeScript (en adelante, TS) del UserComponent.

1. Inyectamos el ActivatedRoute y lo convertimos en propiedad, bautizándolo como routeRecuerda que esta es la forma de acceder a la ruta que esté actualmente activa.

Tenemos una propiedad, user, a la que todavía no le hemos dado uso. Es el momento de hacerlo. A través de ella y del ActivatedRoute podemos acceder a los datos de la URL y rescatarlos (en inglés, fetch). Hacemos esta operación cuando nuestro componente se inicializa, es decir, en el ngOnInit. 

Para acceder a los valores del objeto user (id name), utilizamos una propiedad del ActivatedRoute: snapshota través de la cual accedemos a params, y ahí le pasamos el que queramos rescatarEmpecemos con el id.


  constructor(private route: ActivatedRoute) { }

  ngOnInit() {
    this.user = {
      id: this.route.snapshot.params['id'],
      name:
    };
  }

Como verás, el user object espera dos propiedades (id name). Estas propiedades las rescatará de lo que hayamos definido en nuestros parámetros de la ruta. Es decir, del app.module.ts:

  { path: 'users/:id', component: UserComponent },

Ahí tenemos definido solo un segmento (el id), pero no el name 🙄Vamos a solucionar eso.

  { path: 'users/:id/:name', component: UserComponent },

Con esto, ya podemos rescatar también el name desde el user.component.ts.

      name: this.route.snapshot.params['name']

👉 Podemos añadir todos los parámetros que queramos y rescatarlos de esta manera.

2. Vamos al user.component.html y añadimos los datos del usuario con string interpolation.

<p>User with ID {{user.id}} loaded.</p>
<p>User name is {{user.name}}</p>

Si ahora vas a tu navegador e insertas una URL tipo http://localhost:4200/users/3/Jamie, verás que se te muestra un usuario con esos datos:

routing usuario parametros

Es más, funciona con cualquier dato 🥴. Prueba a poner el número o el nombre que quieras. Como ves, esto no es ideal, y nos encargaremos de arreglarlo más adelante.

Cómo obtener parámetros de una ruta de manera reactiva

En ocasiones, el enfoque utilizado en el apartado anterior no nos será útil. Pongamos un ejemplo.

1. En las dev tools, activamos la memoria caché.

2. En el user.component.html, añadimos un link (que simulará llevarnos al perfil de un usuario) con routerLink incorporado.

3. Lo vinculamos a users con un absolute path con property binding y como segundo segmento le pasamos un número, que actuará como ID. Como tercero le pasamos un nombre, el que queramos también. Esto construirá un ruta que será algo así: http://localhost:4200/users/8/john.

<hr>
<a [routerLink]="['/users', 8, 'john']">John profile</a>

Si guardas y vas a tu navegador, verás que pulsando en el botón "John profile", la URL se actualiza, pero la UI no 🥺.

UI no actualizada - URL sí

Este es el comportamiento por defecto de Angular, y de hecho, a veces ocurrirá aunque la caché esté desactivada. El motivo por el ocurre esto es porque, para empezar, estamos cargando nuestros datos utilizando la propiedad snapshot en la ruta. Pero esto sólo ocurre la primera vez que instanciamos el UserComponent.

Por tanto, cuando ya nos encontramos en el UserComponent e intentamos ir al "perfil de John" pulsando en el botón, Angular no vuelve a instanciar el componente, porque sabe que no hace falta, ya que detecta que ya ha sido instanciado 🧐.

Es cierto que la información del componente ha cambiado al hacer click en el botón "John profile", pero Angular no tiene ni idea de que eso ha ocurrido, porque, ¿cómo se iba a enterar? Nadie se lo ha dicho...y de momento, Angular no es adivino 🧙‍♂️.

Por otro lado, aún suponiendo que Angular se diese cuenta mágicamente que algo ha cambiado en el componente, eso tampoco sería razón para destruirlo y volver a instanciarlo de nuevo, ya que esto supondría un coste a nivel de performance. 

Breve introducción al mundo de los Observables

Utilizar la configuración del snapshot para acceder a la URL en el momento en que el componente se instancia está bien, pero sólo para ese momento. Para todos los cambios que ocurran a posteriori, debemos aplicar otra técnica. Una técnica que permitirá a nuestro código reaccionar a todos los cambios que sucedan después de la inicialización del componente.

Y es que a través de ActivatedRoute podemos acceder a una propiedad llamada paramsque nada tiene que ver con la propiedad params del snapshot, porque el params del ActivatedRoute es un Observable.

Los Observables son una característica que incorpora Angular (indirectamente, a través de una tercera parte, un paquete llamado rxjs) que nos facilita trabajar con tareas asíncronas

El caso que nos ocupa (la tarea de hacer click sobre el botón "John profile" y que la URL cambie) es un caso de tarea asíncrona, ya que no existe manera de saber cuándo el usuario hará click sobre el botón, si es que lo hace en algún momento. Por tanto, no tendría sentido paralizar nuestro código y sentarnos a esperar a que el click suceda ⏳.

Un Observable nos hace esta tarea muy fácil, ya que él solito "observa" en todo momento si cierto evento ocurre, discretamente, sin afectar a la performance de tu app. Si llega el momento en que el evento que estabas esperando sucede (alguien hace click en el botón "John profile"), el Observable nos avisa, ejecutando automáticamente el código vinculado al click del botón. 

Esa manera de "observar" de un Observable se llama "suscribirse a algo" (en inglés, subscribe). Para mí, un Observable es como suscribirse a Netflix 📺. Ya no necesitas estar continuamente buscando cuándo sale el siguiente episodio de Outlander: Netflix te avisa cuando éste está disponible y mientras, tú puedes dedicarte a otras cosas.

Para poder reaccionar a cambios que ocurran después de la inicialización de un componente, debemos usar un Observable.

1. Después de definir el user, accedemos al Observable "params" del router object y nos suscribimos a él usando el método subscribe.

El método subscribe acepta tres argumentos en forma de funciones, siendo el primero el más importante. El primer argumento se dispara cuando el Observable detecta nueva información al haberse producido alguna actividad. Por ejemplo, cuando la URL cambie.

2. Le pasamos como primer argumento una función que acepta como argumento los parámetros actualizados, que será de tipo Params. Dentro de la función, actualizamos las propiedades del user object, dándole los valores que recibiremos en el argumento.

    this.route.params
      .subscribe(
        (updatedParams) => {
          this.user.id = updatedParams['id'];
          this.user.name = updatedParams['name'];
        }
      );

💁 ¡Y listo! Ahora el botón "John profile" ya activa su funcionalidad y la UI se actualiza correctamente.

Este enfoque es el que siempre deberíamos tomar para asegurarnos de que los cambios que sucedan después de la inicialización se reflejen en la template del componente y por tanto, en la UI 🤓.

Pequeña advertencia sobre la vida de un Observable

Podríamos dejar la configuración de nuestro Observable tal y como está y estaría bien, completa. Pero únicamente porque entre bambalinas,

Angular se encargará de limpiar la suscripción al Observable cuando ya no usemos el componente (es decir, cuando se ejecute el ngOnDestroy).

 O lo que es lo mismo, se desuscribirá (en inglés, unsubscribe) por nosotros. 

Si Angular no hiciese esto por defecto, al salirnos del componente la suscripción se quedaría almacenada en alguna parte de la memoria de la app. En el momento en que volviésemos a entrar al componente, un nueva versión del componente se inicializaría y esto ocasionaría un caos 💣.

👩‍🏫 Cuando creemos nuestros propios Observables (más adelante) tendremos que desuscribirnos de ellos manualmente, ya que Angular sólo hace la desuscripción automática con los que trae por defecto, como params. Así que aunque no sea necesario, vamos a aprender a desuscribirnos de estos Observables de Angular.

1. Importamos la interface OnDestroy.

2. Creamos una propiedad para almacenar la suscripción, llamada paramsSubscriptionpor ejemplo. Debe ser de tipo Subscription.

3. Guardamos el Observable dentro de la propiedad paramsSubscription.

4. Implementamos el método ngOnDestroy, desuscribiéndonos del Observable usando el método unsubscribe.

Y esto es lo que ya hace Angular por nosotros en este caso, pero es conveniente que sepamos cómo lo hace, así que podemos borrarlo, aunque yo lo voy a dejar ahí de referencia 🙂.

¡FIN DE LA PARTE #3!

Espero que hayas aprendido algo nuevo 😊.  Si te queda alguna duda, ¡nos vemos en los comentarios! Y si quieres seguir aprendiendo, nos vemos en la parte #4 (disponible próximamente)

Sobre la autora de este post

Soy Rocío, una abogada reconvertida en programadora. Soy una apasionada de aprender cosas nuevas y ferviente defensora de que la única manera de ser feliz es alcanzando un equilibrio entre lo que te encanta hacer y lo que te saque de pobre. Mi historia completa, aquí. 

Si quieres ayudar a hacer este blog sostenible, puedes darme tu apoyo por lo que vale un café ツ

¡Gracias!¡Gracias!

Más recursos de aprendizaje

En mi experiencia, la manera más eficaz para aprender Angular es combinando varias vías de aprendizaje. Uno de mis métodos favoritos son los vídeo-cursos y mi plataforma predilecta para eso es Udemy. He hecho varios cursos pero sólo recomiendo aquellos que verdaderamente me han sido útiles. Aquí van:


Si necesitas apoyo en forma de libro, puede que éstos te sirvan de ayuda:

La programación es un mundo que evoluciona a una velocidad de vértigo. Los autores de estos libros lo saben, por eso suelen encargarse de actualizar su contenido regularmente. Asegúrate de que así sea antes de adquirirlos 😌.

Participo en el programa de afiliados de Udemy y Amazon, lo que significa que, si compras alguno de estos cursos y/o libros, yo me llevaré una pequeña comisión y a ti no costará nada extra. Vamos, lo que se dice un win-win 😊.

Otros artículos que pueden interesarte

Días del 353 al 386
Objetivos versus realidad Y nuevamente, llegó otro día clave. Llegó…y pasó. El pasado 4 de marzo este Reto Computer Geek[...]
Construye Minioland: Tu primera aplicación con Angular | Parte #1
¿Qué vamos a construir?Minioland, o así he decidido llamar a esta sencilla app, totalmente responsive y de tipo Single Page[...]
Angular: Entendiendo la Directiva ngModel
Angular es un framework que nos permite, entre otras cosas, añadir contenido dinámico a nuestros archivos HTML. Una de las formas[...]
Si crees que este post puede serle útil a alguien, por favor, ¡compártelo!:

Deja un comentario

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.

Como toda web legal que se precie, utilizamos cookies para asegurar que damos la mejor experiencia al usuario en nuestro sitio web. Si continúas utilizando este sitio asumiremos que estás de acuerdo. más información

Los ajustes de cookies de esta web están configurados para "permitir cookies" y así ofrecerte la mejor experiencia de navegación posible. Si sigues utilizando esta web sin cambiar tus ajustes de cookies o haces clic en "Aceptar" estarás dando tu consentimiento a esto.

Cerrar