Implementación de Angular
Introducción
Desde hace varios años, el mundo del desarrollo web ha visto la llegada de innumerables frameworks y otras librerías JavaScript para hacer la vida más fácil a los desarrolladores front-end. Uno de ellos, AngularJS, se ha consolidado como uno de los frameworks más populares de su generación, ofreciendo una metodología robusta para hacer el código cliente mucho más mantenible y eficiente. En concreto, el objetivo de AngularJS es ofrecer la metodología MVC en el lado del cliente y, al mismo tiempo, aportar las ventajas de una Single Page Application con la potencia del lenguaje JavaScript.
Anunciada hace casi dos años, la versión 2 del famoso framework está a punto de finalizarse, ofreciendo ya una base extremadamente sólida para construir aplicaciones web modernas. En colaboración con el equipo de Microsoft encargado del lenguaje TypeScript, el equipo de Angular ha reescrito y replanteado por completo el framework para aportarle el rendimiento que le faltaba, pero también para aprovechar toda la potencia de la sintaxis de TypeScript para diseñar un código limpio y mucho más mantenible de lo que podía ser antes.
Este capítulo cubrirá los puntos más importantes de Angular, a la vez que mostrará cómo el framework ha aprovechado lo mejor de HTML 5 y TypeScript. Como la noción...
Las nuevas API HTML 5
Durante mucho tiempo, la Web se diseñó utilizando etiquetas <div> y <span>, que en definitiva añadían muy poca verbosidad al código HTML escrito por el desarrollador. Por supuesto, hay clases CSS que facilitan el estilo de las etiquetas, pero desde un punto de vista puramente HTML, el código tiene muy poca estructura.
¿No sería mejor poder crear y utilizar una etiqueta <left-menu> para un menú vertical, una etiqueta <grid> para diseñar una cuadrícula o incluso una etiqueta <notification> para diseñar un centro de notificaciones para la aplicación? HTML 5 permite ahora este tipo de escritura mediante la autorización de elementos personalizados.
Los elementos personalizados permiten a los desarrolladores web diseñar sus propios tipos de elementos HTML, sentando las bases para el concepto más amplio de componentes web (que se explica en la siguiente sección). Estos nuevos elementos permiten:
-
definir nuevos elementos HTML/DOM,
-
crear elementos que amplíen otros elementos,
-
diseñar funciones personalizadas reunidas en un único paquete lógico e identificadas por una única etiqueta,
-
amplían las API de otros elementos del DOM.
La base para cualquier creación de un nuevo elemento HTML 5 proviene del método document.registerElement()en JavaScript. El código siguiente muestra cómo crear un elemento desde cero:
var TestAngular = document.createElement('test-angular);
document.body.appendChild(new TestAngular());
El resultado es el siguiente código HTML, que se inserta en el DOM de la página:
<test-angular></test-angular>
La denominación de los elementos es muy importante. Todos los navegadores soportan una lista finita de elementos HTML conocidos. Los elementos desconocidos, como <ciudad> o <cliente> no causarán necesariamente un error en el analizador sintáctico de HTML y, en su lugar, se definirán como elementos desconocidos a través de la interfaz HTMLUnknownElement. El estándar W3C recomienda añadir un guion (-) a cada elemento personalizado añadido por el desarrollador para que el analizador HTML pueda distinguirlo. Esto también previene futuros cambios en el estándar al evitar colisiones...
El concepto de componente
Angular se centra decididamente en los nuevos estándares de la Web moderna, implementando muchas de las nuevas API y ofreciendo una metodología de desarrollo del lado del cliente rica y flexible. El corazón de Angular se centra ahora en un único concepto: los web components.
En términos sencillos, un componente web es una fusión de los principios fundamentales descritos en la sección anterior: importaciones, elementos personalizados y el Shadow DOM. El uso de un web components tiene varias ventajas:
-
El uso del Shadow DOM permite trabajar sólo en una pequeña parte del DOM y no en todo el DOM de la página. Como resultado, al manipular elementos HTML, el proceso es más eficiente porque sólo se explora una parte del DOM.
-
Encapsulación de estilos para evitar colisiones entre diferentes CSS.
-
Reutilización de componentes mediante la importación.
-
Creación automática y limpieza de elementos personalizados.
-
La separación del DOM y el código fuente es mucho más sencilla y clara, al tiempo que se mantiene una capacidad de mantenimiento eficaz.
-
Las páginas son más ligeras de cargar.
Sin embargo, los componentes web se pueden volver rápidamente desorganizados y complejos si el desarrollador construye elementos demasiado grandes. Aquí es donde entra Angular, que ofrece una respuesta eficiente y organizada a la complejidad de los web components.
Desde el punto de vista de Angular, la conclusión es muy clara: todo es un componente. Esto significa que cada parte de la aplicación web debe ser un web component para mejorar el rendimiento y el dinamismo del sitio. Incluso toda la aplicación debe ser un web component que, a su vez, interactuará con otros componentes para la recuperación de datos o la navegación. Al final, el desarrollador construye un árbol de componentes que se pueden comunicar entre sí.
Ejemplo de árbol de dependencias de un componente Angular.
Originalmente, la primera versión de AngularJS proponía implementar el patrón MVC (Model - View - Controller) en el lado cliente en JavaScript para lograr un mejor desglose de las capas. A medida que avanzaron las distintas versiones y reelaboraciones de código del framework, AngularJS tendió en su lugar a implementar un patrón...
Los diferentes metadatos
La sección anterior destacó la noción de un componente Angular y la filosofía detrás de todo el framework. Los ejemplos mostraron que un componente es, en última instancia, una simple clase TypeScript. Entonces, ¿cómo puede Angular interpretar esta clase como un componente web? Gracias a los metadatos.
Un metadato se utiliza para dar información a Angular para que pueda realizar un cierto número de operaciones sobre la clase dependiendo del tipo de metadato. Los metadatos se añaden a través de decoradores, como @Component que estaba presente en los ejemplos anteriores. El siguiente código añade metadatos a una clase TypeScript para añadir funcionalidades Angular:
@Component({
selector: 'product-list',
templateUrl: 'app/product-list.component.html',
directives: [ProductDetailComponent],
providers: [ProductService]
})
export class ProductsComponent { ... }
Aquí el decorador indica que la clase ProductsComponent es un componente Angular. Los decoradores son nada más y nada menos que funciones, tomando como entrada un objeto de configuración que luego será procesado por Angular para realizar las acciones necesarias (recuperar la vista, inyectar servicios, etc.).
El ejemplo anterior contiene la siguiente información de configuración:
-
selector: selector CSS que permite a Angular crear el componente en cuanto encuentra la etiqueta <product-list> en el HTML padre. Por ejemplo, Angular podrá sustituir el siguiente código HTML por el componente correspondiente:
<product-list></ product -list>
-
templateUrl: la ruta hacia la vista del componente.
-
directives: matriz de componentes o directivas requeridas por la plantilla. En concreto, el ProductsComponent probablemente necesitará otros componentes para funcionar (por ejemplo, un componente para mostrar los detalles de un producto). Cada uno de los demás componentes utilizados por la plantilla a través de elementos personalizados, tendrán que indicar en directives el tipo de componente a utilizar (<product-detail> pedirá que indique un ProductDetailComponent en la configuración)....
Lanzamiento de una aplicación Angular
Los decoradores son una forma muy eficaz de estructurar una aplicación Angular y diseñar componentes HTML 5 de una manera ágil. El framework se encarga de instanciar los componentes, recuperar las vistas y gestionar las dependencias y el desarrollador solo tiene que codificar la funcionalidad que necesita para satisfacer sus requisitos.
Escribir los componentes es una cosa, pero luego estos componentes necesitan instanciarse y vivir a través de la página con el fin de responder a las diversas interacciones del usuario. Este proceso se llama bootstrapping, y permite lanzar componentes Angular.
Para que su primer componente funcione, primero necesita importar e integrar todos los scripts que Angular necesita para funcionar. Los paquetes NPM son los siguientes:
-
Todos los módulos de Angular: @angular/common, @angular/core o @angular/http para el funcionamiento del framework.
-
SystemJS: un module-loader (carga de las librerías y dependencias sobre la marcha) universal y popular en JavaScript.
-
Es6-shim: compatibilidad con ECMAScript 6 para motores JavaScript.
-
Reflect-metadata: funcionalidad de reflexión para metadatos escritos en ECMAScript 6.
-
RxJS: programación asíncrona y basada en eventos.
-
Zone.js: contexto de ejecución persistente a través de tareas asíncronas. Esta librería se utiliza en particular para actualizar automáticamente la vista cuando se asigna una propiedad desde otra tarea.
Las dependencias que se deben insertar en el archivo package.json, son las siguientes:
"dependencies": {
"@angular/common": "2.0.0-rc.1",
"@angular/compiler": "2.0.0-rc.1",
"@angular/core": "2.0.0-rc.1",
"@angular/http": "2.0.0-rc.1",
"@angular/platform-browser": "2.0.0-rc.1",
"@angular/platform-browser-dynamic": "2.0.0-rc.1",
"@angular/router":...
Navegación
La navegación es una característica común de un sitio web: los usuarios exploran la aplicación a través de las URL que definen la página en la que se encuentran. Este proceso también les permite escribir directamente la URL que deseen y el sitio web responderá con la página correspondiente. Por eso es importante disponer de un sistema coherente y fiable para traducir cada URL, con una página web proporcionada por el servidor: son las llamadas rutas.
Angular tiene un componente dedicado al enrutamiento en la aplicación: el componente enrutador (o router). Este componente interpreta las URL del navegador para navegar a una página generada por el cliente. Es importante recordar que Angular sólo funciona en el lado del cliente, por lo que la navegación en el lado del servidor simplemente cortocircuitaría el funcionamiento de Angular, reiniciando todos los componentes cada vez que se actualiza la página. El framework incorpora un buen número de conceptos que serán examinados en esta sección.
El concepto de navegación con Angular se basa enteramente en componentes. Cuando una aplicación Angular navega de URL a URL, en realidad está navegando de componente a componente y los propios componentes pueden definir rutas a nuevos componentes, y así sucesivamente. No es necesario definir todas las rutas a nivel del componente raíz y tampoco es necesario definir plantillas de rutas.
En primer lugar, y para que Angular funcione correctamente, el desarrollador debe integrar una etiqueta bastante especial que es <base href="/"> en el index.html, después de la etiqueta <head>. Esta etiqueta permitirá definir rutas relativas, componente por componente.
Para entender cómo funciona, imaginemos una aplicación con cuatro páginas: una lista de productos, un detalle del producto, una lista de ventas de este producto y, por último, una página con los detalles de la venta. La lista de ventas sería accesible a través del detalle del producto. Tendríamos entonces las siguientes rutas:
-
/products: lista de todos los productos.
-
/products/25: detalles del producto con ID 25.
-
/products/25/sales: lista de todas las ventas del producto ID 25.
-
/products/25/sales/12: detalles de las ventas de ID 12 del producto...