Adaptando el proyecto

Para empezar a trabajar con Angular 6 vamos a partir del último CRUD que hicimos en el curso introductorio de Angular 5. Así veremos las modificaciones necesarias (muy pocas, realmente) y, como ya estamos familiarizados con todas las técnicas que emplea el CRUD, nos será mucho más fácil empezar a aprender cosas nuevas.

Es este curso vamos a ir mejorando y ampliando nuestro CRUD y lo finalizaremos desarrollando una aplicación completa con las prestaciones más usuales de Angular. Fíjate que digo las más usuales, porque, si quisiéramos conocer todas las prestaciones de este framework necesitaríamos una enciclopedia que, seguramente, no cabría en el salón de la mayoría de las casas (en la mía no, desde luego). A día de hoy, esta herramienta tiene tantas prestaciones que dudo mucho que nadie se las conozca todas. Sin embargo, las que conoceremos en este curso nos abrirán cualquier salida profesional, ya sea laboral o freelance.

Vamos a ello.

MODIFICACIONES NECESARIAS

Si copiamos el código del CRUD con el que cerrábamos el curso anterior, y tratamos de ejecutarlo, veremos que no nos funciona en modo alguno. Sin embargo, las modificaciones de código reales son mínimas.

Lo primero es que, como ya sabes, ha desaparecido el fichero .angular-cli.json, por lo que debes eliminarlo de tu aplicación. En su lugar, usaremos angular.json, que se ha instalado con el nuevo proyecto, ahora que ya tenemos el CLI de Angular 6.

El siguiente punto que tienes que revisar es el servicio que empleamos para conectar con las API’s (HttpConnectService). En el código de este servicio, en la parte superior, donde se hacen las importaciones, tenemos la siguiente línea:

import { Observable } from 'rxjs/Observable';

Debemos cambiarla por:

import { Observable } from 'rxjs';

En este proyecto no hay más modificaciones que se puedan considerar estrictamente necesarias. El resto del proyecto funciona perfectamente tal como está. Como ya te comenté, son pocos los cambios de Angular 5 a 6.

MODIFICACIONES OCASIONALES

Sí hay otros cambios importantes. El primero es que, con Angular 6, ya no tenemos problemas para usar bootstrap 4. Por supuesto, puedes perfectamente seguir usando la versión 3. Si optas por esto último, puedes saltarte este apartado.

Si empleas bootstrap 4, que sepas, de entrada, que los glyphicons han desaparecido. La última versión de bootstrap no incluye una librería propia de iconos, para que cada uno pueda usar los que desee. En el mercado hay gran cantidad de librerías que puedes usar, algunas libres y otras de pago. En la misma página de bootstrap de da varias sugerencias al respecto (https://getbootstrap.com/docs/4.1/extend/icons/). Nosotros hemos optado, de momento, por ionicons (https://ionicons.com/), aunque tú puedes optar por la que desees. Puedes instalarla en tu proyecto con:

npm install ionicons

No olvides modificar el fichero angular.json, para referenciar la librería:

Por supuesto, migrar de bootstrap 3 y sus glyphicons a bootstrap 4 (donde los nombres de algunas clases cambian ligeramente) y usar una librería externa, implica algunos cambios menores en el HTML, en el TypeScript y en CSS, donde tienes que referirte a las nuevas clases. Los verás en el código de la aplicación. Son pocos, ya que nuestra aplicacióne es, aún, muy sencilla, pero importantes.

CUESTIONES PROGRAMÁTICAS

Si te fijas en detalle en la estructura de archivos, verás que te falta uno que pasaba muy desapercibido. Se trata de src/typings.d.ts. Este archivo ha sido suprimido en la nueva versión, y por una buena razón: los desarrolladores solíamos emplearlo, en muchas ocasiones, para declarar variables como las siguientes:

declare var jQuery: any;
declare var $: any;

Esto hacía que estuvieran disponibles para toda la aplicación, y no tuviéramos necesidad de declararlas en cada componente donde fuéramos a usar jQuery. A priori, parece una solución muy conveniente. Sin embargo, da un problema. Cuando se instalan ciertas librerías externas, algunas de ellas incluyen, en las últimas versiones, dependencias que ya declaran estas variables. Eso hace que se produzca una colisión de redeclaración de variables al compilar.

Los fabricantes de Angular no tienen aún este punto totalmente solucionado. Es de esperar que, en futuras versiones, lo arreglen de algún modo pero, por ahora, no nos queda más remedio que prescindir de typings.d.ts y declarar las variables mencionadaas en cada componente que vaya a usar jQuery. Además, si algúno de esos componentes va a usar una librería externa cuyas dependencias ya declaren las variables jQuery y $ tendremos que tener cuidado de no redeclaraarlas manualmente, para evitar colisiones.

ATENCIÓN. La declaración de estas variables en la lógica del componente es necesaria si el uso de jQuery se va a hacer sobre elementos que formen parte de la vista de dicho componente. Si no, podemos omitirla. Por ejemplo. En el componente MemberFormComponent, donde se actúa por jQuery sobre el campo de fichero de la imagen, que está en member-form.component.html, es necesaario declararlas. Sin embargo, en HomeComponent, donde dólo se actúa por jQuery sobre el objeto document, pero no sobre ningún elemento propio del componente, podemo omitirla.

Ahora, quiero hablarte de una mejora importante sobre la barra de navegación. Es algo que, en su momento, aprendimos a hacer «por la vía fácil», porque nos venía bien, pero que ahora podemos optimizar. Lo que vamos a ver ahora podríamos, también, haberlo visto con Angular 5 y bootstrap 3. Sin embargo, he preferido reservarlo para Angular 6 y bootstrap 4, ya que son las últimas versiones disponibles en la actualidad y, como la forma de crear las barras de navegación presenta alguna ligera diferencia en bootstrap con los menús desplegables, así introducimos esta mejora con la versión actual.

Se trata del hecho de que, cuando se carga un componente, se le añade la clase active al enlace correspondiente en la barra de menús de forma que, viendo el enlace resaltado, ya sabemos que componente está cargado. Esto, hasta ahora, lo hemos hecho de forma artesanal. Al inicio de cada componente, en el método ngOnInit(), quitábamos la clase active a todos los enlaces, y después se la añadíamos, de modo expreso, al enlace que nos había llevado hasta ese componente. Además, si el enlace estaba en un menú desplegable de la barra de navegación, le añadíamos, también con jQuery, la clase active al nombre del menú. Por ejemplo, en la lista de miembros (MembersListComponent), teníamos algo como esto:

Como hemos visto, eso nos funcionaba bien, pero nos obligaba a tres cosas:

  • Ponerle a los enlaces una clase específica, para poder referenciarlos todos globalmente (la clase menuLink). Cuando hay dos o tres enlaces, es molesto, pero no pasa de hay. Pero si nuestra aplicación tuviera quince o veinte enlaces, distribuidos en varios submenús, sería inmanejable.
  • Además, tenemos que darle a cada enlace un identificador, a fin de poder añadirle la clase active desde jQuery a un enlace específico.
  • Y en cada componente tenemos que añadir dos o tres líneas adicionales de jQuery, lo que no deja de ser molesto, poco práctico y, a la larga, un potencial foco de errores.

Existe un recurso de Angular que podemos implementar, únicamente, en la barra de navegación, y cuando se cargue un componente se mostrará activo. Se trata de la directiva routerLinkActive. Se la asociamos a cada enlace, asígnándole la clase active. A partir de ahí, cada vez que pulsemos un enlace, se cargará el componente y se mostrará activo dicho enlace. Por ejemplo, el enlace de la página de inicio podría quedar así:

<a class="nav-link" routerLink="" routerLinkActive="active">Inicio</a>

Sin embargo, esto presenta un problema. Si el destino del enlace (routerLink) coincide parcialmente con otro enlace parecido, se podrían mostrar activos dos enlaces simultáneamente. Afortunadamente, Angular tiene un mecanismo complementario para evitar esto. Se trata de la directiva routerLinkActiveOptions, a la que le indicamos que queremos el valor exacto del enlace, así:

<a class="nav-link" routerLink="" routerLinkActive="active" [routerLinkActiveOptions]="{exact: true}">Inicio</a>

La sintaxis de esta última puede parecer un poco confuso, ya que recuerda al binding de propiedades, por los corchetes que rodean a la directiva. Realmente es lo que es. La propiedad routerLinkActiveOptions está recibiendo, como valor, el dato {exact: true}. Una vez que te familiarizas con esto, no tiene más importancia, y nos soluciona el problema de los enlaces activos tocando sólo en la barra de navegación.

La cosa se puede poner un poco más engorrosa cuando tenemos que aplicar esta técnica a un enlace que pertenece a un submenú, ya que debe quedar activo el enlace que se pulsa, y el nombre del submenú al que corresponde. En realidad es muy fácil. Tenemos un ejemplo en el menú de miembros, que tiene dos opciones (de momento). Mira el siguiente fragmento.

Como ves, es mucho más simple que andar modificando el estado de los enlaces desde jQuery en cada componente. Y, sobre todo, cuando nuestra aplicación crezca, será mucho más fácil escalarla con menos trabajo, y, sobre todo, con menos errores.

CONCLUYENDO

Ya tenemos el CRUD preparado y adaptado a las últimas novedades, para seguir aprendiendo a partir de aquí. Como siempre, te dejo en este enlace la aplicación en su estado actual. Hemos mantenido el nombre del proyecto, y el prefijo. Una vez descargados los ficheros y copiados en el directorio de tu proyecto no olvides (esto ya lo sabes) hacer npm install, para que, a partir del package.json, se te copien las herramientas que necesitas (jQuery, bootstrap 4 e ionicons). Nos vemos en el siguiente artículo.

   

Deja un comentario