Rutas con parámetros en carga directa

En este artículo vamos a empezar a ver las rutas con parámetros, es decir, que, al acceder a una vista, podamos pasarle uno o más parámetros, y la vista reciba esos parámetros para poder procesarlos.

En una aplicación como la que estamos creando podría ser bueno, por ejemplo, para que al seleccionar la lista de clientes nos muestre una serie de enlaces, relativos a cada uno de los clientes. Al pulsar un enlace nos mostraría la ficha del cliente correspondiente. Todos los enlaces van a la misma vista, y lo único que cambia es el cliente que muestra.

Esto se puede hacer en módulos de carga directa, o en módulos de carga diferida. El concepto es el mismo, aunque, con los de carga directa (como es el caso de nuestra sección de clientes), y los de carga diferida hay algunos detalles diferentes.

El proceso es un poco complejo de entender la primera vez, pero luego verás que es, conceptualmente, muy lógico y limpio.

LO QUE NECESITAMOS

Lo que vamos a hacer en este artículo es incorporar en la vista de clientes una lista de los clientes registrados. Por supuesto, en caso de una aplicación real, estos datos procederían de una API, o un Web Service, que nos los proporcionase a partir de una base de datos. Sin embargo, dado que aún no hemos hablado de comunicaciones con el servidor, los vamos a crear en código, como datos «fijos».

El siguiente paso es cresr los enlaces de forma que carguen el componente CustomerDataComponent, que ya tenemos creado, pero que aún no tiene contenido.

Y hay que entender esto. Evidentemente, no se va a crear una ruta y un componente por cada cliente. El componente y su vista serán siempre los mismos, y en la ruta incorporaremos un parámetro que, en este ejemplo, será el identificador del cliente. Puede ser un ID, su CIF o lo que decidamos. En una aplicación real (y volvemos a lo mismo) a partir de ese identificador se obtendrían los datos del cliente de una base de datos. Aquí los vamos a tener como datos «fijos». A lo otro ya llegaremos. Después de todo, por ahora sólo se trata de ver cómo pasar parámetros en la ruta, y recibirlos en el componente de destino para hacer «algo» con ellos.

LA LISTA DE CLIENTES

Vamos a modificar la vista de CustomersListComponent (customer-list.component.html) para incluir los enlaces a la vista de datos de cliente, con los identificadores de los supuestos clientes, así:

Observa los enlaces. En cada uno se llama a la misma ruta (que en seguida definiremos en el enrutador), seguida de una barra y un identificador de cliente, que es el parámetro variable que pasamos en la ruta. Es decir, apuntamos siempre a la misma ruta, pero con un parámetro que cambia en cada llamada. Y observa también que el enlace empieza por «subir un nivel», es decir, con ../. Esto es porque el componente del listado de clientes no está en el módulo raíz de la aplicación, si no en un módulo que está a la misma altura jerárquica que la vista de la ficha de cliente. En cuanto veas el enrutador lo entenderás.

EL ENRUTADOR

Para esto vamos a usar el enrutador raíz, es decir, app-routing.module.ts. La razón de usar este enrutador es que, como el módulo de clientes lo cargamos en directo, es decir, sin lazy load, y el enlace de la lista de clientes en la barra de navegación también apunta a una ruta de este enrutador, así tenemos las rutas organizadas en el mismo script de enrutamiento. Le añadimos la route correspondiente, así:

Observa la ruta en las líneas de la 19 a la 22. La hemos llamado con el mismo nombre que el enlace en customers-list.component.html. Es lo mismo que hacemos con las demás rutas, que las llamamos como aparecen en los enlaces de la barra de navegación. Sin embargo, la ruta que nos interesa ahora tiene una peculiaridad. Después del nombre de la propia ruta tiene la partícula /:id. Esto significa dos cosas: que la ruta continúa con otra ruta relativa (de ahí el slash /) y que lo que viene a continuación se debe entender como un parámetro. Esto nos lo indica el signo de dos puntos (:) que precede a id. El nombre id que le hemos dado al parámetro lo elegimos nosotros al construir la ruta.

Y aquí vemos la razón de que los enlaces de la vista del componente de listado de clientes los precediéramos con ../. Como ambos componentes están al mismo nivel jerárquico, y tenemos que pasar de uno a otro, si no «subimos» un nivel la vista de detalle del cliente se buscaría un nivel por debajo de la lista de clientes. Es decir, los enlaces, desde el listado de clientes, apuntarían, por ejemplo, a localhost:4200/clientes/ver_cliente/108 en lugar de apuntar localhost:4200/ver_cliente/108. Como esa ruta no sería correcta, sólo llegaríamos a la vista de NotFoundComponent.

ATENCIÓN. Esto no es nada nuevo. Por mucho que el enrutador nos facilite crear un sistema de enrutamiento que funcione bien en toda la aplicación, y que sea único para todo el ciclo de vida de la aplicación, los enlaces relativos se basan en las mismas premisas que han funcionado desde siempre en HTML. No sólo tienes que tener en cuenta «a donde va el enlace», si no también «desde donde va». En realidad, aunque el enrutador de Angular pueda resultar un poco chocante la primera vez que se usa, esto son rutas relativas «de toda la vida».

Por lo demás, en la línea 5 ves como importamos el componente CustomerDataComponent, que referenciamos en la ruta. De esto casi no tendremos que preocuparnos, ya que, al escribir el nombre en la propiedad component de la ruta, VSC hace esa importación de modo automático por nosotros, pero es bueno saber que está ahí, y por qué.

RECIBIR E IDENTIFICAR EL PARÁMETRO

Y esta es la última fase que queda (por lo menos, por ahora). ¿A dónde va ese parámetro? ¿Quién lo recibe y quién hace qué con él?. Bueno. Está claro que lo que sea ocurre en CustomerDataComponent. El parámetro, lógicamente, se recibe e identifica en la lógica de negocio, es decir, en customer-data.component.ts. Observa el siguiente código:

Vamos a empezar mirando la clase que se exporta, llamada CustomerDataComponent, que es la que contiene la lógica de negocio del componente. Lo primero que hacemos es definir una variable a la que he llamado identifier, por darle un nombre descriptivo y distintivo. En el constructor de la clase creamos una variable privada a la que hemos llamado customer. Fíjate que la hemos definido como de tipo ActivatedRoute. Este es un tipo de dato personalizado que define Angular, y tenemos que importar la definición, como ves en la línea 2. Esta importación te la incluye el VSC automáticamente al usar el tipo pero, si tu editor no lo hace, tendrás que incluir tú la importación de forma manual. Al definir la variable como private y como un argumento del constructor, esta variable «vive» en todo el ámbito de la clase pero, al mismo tiempo, queda encapsulada de forma que evitamos que pueda ser alterada, por error, desde fuera de esta clase. Además, al quedar encapsulada en la clase, evitamos que pueda colisionar con otra variable externa que tuviera el mismo nombre. La variable identifier la dejamos sin modificador de acceso (lo que equivaldría a ponerle el modificador public), porque luego la necesitaremos ver desde fuera de la clase.

A continuación tenemos que fijarnos en la parte definida con ngOnInit. Esta es una directiva de las clases que no es, realmente de JavaScript, sino que es del propio Angular (observa que lo importamos en la línea 1). En concreto, esta detecta cuando se inicializa (se carga) el JavaScript del módulo. Detecta este evento, y responde a él con «algo» (las instrucciones contenidas en el cuerpo del evento). Para que te hagas una idea, sería (salvando las diferencias) el equivalente al window.onload(); de JavaScript, o al $(document).ready(); de jQuery, al menos desde el punto de vista conceptual de «algo» que se ejecuta cuando se carga el componente. Es sólo que, en Angular se llama ngOnInit, pero el concepto es el mismo.

Y aquí es donde viene la cuestión. La variable customer recibe el parámetro id que se envió en el enlace, y que en la ruta está precedido por :.  Sin emabrgo, lo recibe en una estructura propia de Angular. Es necesario extraerlo y asignárselo a la variable identifier. De esto se ocupa la instrucción de la línea 16. De momento, simplemente acepta que es así. Ya hablaremos de la sintaxis de esta instrucción más adelante, ya que los snapshot es un concepto del que aún no hemos tratado.

MOSTRAR EL PARÁMETRO

Bien. Una vez que tenemos el parámetro enviado en la variable identifier, mostrarlo en la vista es una simple interpolación de variables, como ves en customer-data.component.html:

CARENCIAS

Esta forma de hacer esto presenta importantes carencias. Por ejemplo, sólo estamos mostrando el id del cliente, no sus datos. Como ya hemos mecionado arriba, los datos del cliente deberían ser accesibles a través de una API, desde la lógica de negocio del componente. Sin embargo, esto es harina de otro costal. Además, si tecleamos en la barra de direcciones el acceso a un cliente que no exista en la lista de enlaces, nos lo muestra igual. Por ejemplo, sin tecleas localhost:4200/ver_cliente/89056 vas a obtener la misma vista de CustomerDataComponent, en la que verás ese identificador, como si hubieras llegado desde un enlace. Esto también es parte de lo que nos falta por filtrar en la lógica de negocio. Poco a poco. En el presente artículo se trataba de ver como se pasan y reciben parámetros por la URL, y eso lo hemos hecho.

EL RETORNO

Podemos mejorar la vista de CustomerDataComponent, con un enlace que nos devuelva a la lista de clientes. En realidad, es un enlace que debe apuntar a una ruta que ya existe (clientes), por lo que ni siquiera debemos tocar el enrutador. Sin embargo, en el enlace tenemos que añadir un pequeño retoque, que ya nos empieza a ser familiar, como ves en esta versión de customer-data.component.html:

Observa que el enlace sube dos niveles (../../), para poder alcanzar el path correcto en el enrutador. Esto se debe a que en la URL que tenemos ahora (mira la barra de direcciones) estamos dos niveles por debajo de la raíz del sitio, y como el enrutador está en la raíz (AppComponent), tenemos que llegar primero ahí, y luego acceder a la ruta.

CONCLUYENDO

En este artículo hemos aprendido a pasar parámetros en una URL, y recibirlos desde un componente que pertenece a un módulo de carga inmediata. Si te surge algún problema, puedes revisar todo el código en este enlace. En el próximo artículo veremos como hacer lo mismo, con un módulo en carga perezosa.

   

Deja un comentario