Manual De Angular Angular7
User Manual:
Open the PDF directly: View PDF
.
Page Count: 141
| Download | |
| Open PDF In Browser | View PDF |
INDRA OPEN UNIVERSITY PRESENTACION DEL CURSO 1 ESCUELA: TECNOLOGÍA ANGULAR 2+ 13 1 ÍNDICE ▪ Introducción a TypeScript ▪ Introducción a Angular 2+ ▪ Herramientas de Desarrollo ▪ Módulos ▪ Plantillas ▪ Formularios ▪ Servicios ▪ Acceso al servidor ▪ Enrutamiento y navegación Título del documento | 15 15 ESCUELA: TECNOLOGÍA ANGULAR 2.0 ▪ NOMBRE APELLIDO PROFESOR Javier Martín ▪ VER PERFIL COMPLETO: ▪ CONTACTO jmartin@grupoloyal.com Título del documento | 16 16 2 Angular 7 https://angular.io/ © JMA 2016. All rights reserved 20 Contenidos • Introducción a TypeScript – – – – • Introducción a Angular 2 – – – – – • • • Instalación de utilidades Creación de una aplicación Estructura de la aplicación Librerías de terceros Metadata Módulo principal Módulos de características Módulos Angular 2 vs JavaScript – – – – Clases como servicios Dependency injection Proveedores Inyectores • Vinculación bidireccional Validaciones Estilos visuales Acceso al servidor – – – – Servicios Data binding Marcadores Directivas Transformaciones (Pipes) Formularios – – – • Selectores especiales Encapsulación Preprocesadores CSS Plantillas – – – – • Plantillas y estilos Propiedades de entrada Eventos de salida Ciclo de vida Estilos – – – Módulos – – – – • Características Angulas JS vs Angular 2 Arquitectura Elementos estructurales Model View ViewModel (MVVM) Componentes – – – – Herramientas de Desarrollo – – – – • • Sistema de tipos Sintaxis ampliada Clases, herencia, genéricos e interfeces Módulos y decoradores Patrón Observable (RxJS). HttpModule y JsonpModule Servicios RESTFul JSONP Enrutamiento y navegación – – – – RouterModule Definición de rutas Paso de parámetros Navegación © JMA 2016. All rights reserved 21 3 INTRODUCCIÓN A ANGULAR 2+ © JMA 2016. All rights reserved 22 Arquitectura Web • Una aplicación Web típica recogerá datos del usuario (primer nivel), los enviará al servidor, que ejecutará un programa (segundo y tercer nivel) y cuyo resultado será formateado y presentado al usuario en el navegador (primer nivel otra vez). © JMA 2016. All rights reserved 23 4 Single-page application (SPA) • Un single-page application (SPA), o aplicación de página única es una aplicación web o es un sitio web que utiliza una sola página con el propósito de dar una experiencia más fluida a los usuarios como una aplicación de escritorio. • En un SPA todo el códigos de HTML, JavaScript y CSS se carga de una sola vez o los recursos necesarios se cargan dinámicamente cuando lo requiera la página y se van agregando, normalmente como respuesta de los acciones del usuario. • La página no se tiene que cargar otra vez en ningún punto del proceso, tampoco se transfiere a otra página, aunque las tecnologías modernas (como el pushState() API del HTML5) pueden permitir la navegabilidad en páginas lógicas dentro de la aplicación. • La interacción con las aplicaciones de página única pueden involucrar comunicaciones dinámicas con el servidor web que está por detrás, habitualmente utilizando AJAX o WebSocket (HTML5). © JMA 2016. All rights reserved 24 Introducción • • • • • • • Angular (comúnmente llamado "Angular 2+" o "Angular 2") es un framework estructural para aplicaciones web de una sola página (SPA) siguiendo el patrón MVVM y orientación a componentes. Permite utilizar el HTML como lenguaje de plantillas y extender la sintaxis del HTML para expresar los componentes de la aplicación de forma declarativa, clara y sucinta . El enlazado de datos y la inyección de dependencias eliminan gran parte del código que de otra forma se tendría que escribir. Y todo sucede dentro del navegador, lo que lo convierte en un buen socio para cualquier tecnología de servidor. Angular es un framework que pretende definir la arquitectura de la aplicación. Define claramente la separación entre el modelo de datos, el código, la presentación y la estética. Estás obligado por Angular a seguir esa estructura. Ya no haces el JavaScript como tu quieres sino como Angular te manda. Y eso realmente da mucha potencia a la aplicación ya que, al seguir una arquitectura definida, Angular puede ayudarte en la aplicación y a tener todo mucho mas estructurado. Angular es la evolución de AngularJS aunque incompatible con su predecesor. © JMA 2016. All rights reserved 25 5 Novedades • En AngularJS la escalabilidad estaba limitada por: – Lenguaje JavaScript – Precarga del código. • • • • • • • • • Uso de TypeScript: validación, intellisense y refactoring. Desarrollo basado en componentes. Uso de Anotaciones (metadatos): declarativa frente a imperativa. Doble binding, se ha reconstruido según el patrón observable, las aplicaciones son hasta cinco veces más rápidas. La inyección de dependencias, carga dinámica de módulos. Incluye compilación AoT (Ahead of Time - Antes de tiempo, que es una forma de compilar todo el código JS, incluyendo plantillas de manera anticipada, restando carga de trabajo al navegador) y también lazy-loading (descarga bajo demanda, una manera de sólo descargar los recursos realmente necesarios en cada momento). Aparición de Angular Universal (herramienta de renderizado de Angular desde el servidor), podemos ejecutar Angular en el servidor. Aplicaciones híbridas, solución low cost para aplicaciones móviles. Está cada vez más orientado a grandes desarrollos empresariales. © JMA 2016. All rights reserved 26 Características • Velocidad y rendimiento – Generación de código: Angular convierte sus plantillas en un código que está altamente optimizado para las máquinas virtuales de JavaScript de hoy, brindándole todos los beneficios del código escrito a mano con la productividad de un marco. – Universal: Sirva la primera vista de su aplicación en Node.js, .NET, PHP y otros servidores para renderización casi instantánea en solo HTML y CSS. También allana el camino para sitios que optimizan para SEO. – División del código: Las aplicaciones Angular se cargan rápidamente con el nuevo enrutador de componentes, que ofrece división automática de códigos para que los usuarios solo carguen el código requerido para procesar la vista que solicitan. • Plataformas cruzadas – Aplicaciones web progresivas: Utilice las capacidades de la plataforma web moderna para ofrecer experiencias similares a las de las aplicaciones de escritorio o nativas. Instalación de alto rendimiento, fuera de línea y en cero pasos. – Nativo: Cree aplicaciones móviles nativas con estrategias de Cordova, Ionic o NativeScript. – Escritorio: Cree aplicaciones instaladas en el escritorio en Mac, Windows y Linux utilizando la misma metodología Angular que ha aprendido para la web y la capacidad de acceder a las API nativas del sistema operativo. © JMA 2016. All rights reserved 27 6 Características • Productividad – Plantillas: Cree rápidamente vistas de IU con sintaxis de plantilla simple y potente. – Angular CLI: Herramientas de línea de comandos: comience a construir rápidamente, agregue componentes y pruebas, y luego implemente al instante. – IDEs: Obtenga la finalización inteligente de códigos, errores instantáneos y otros comentarios en editores e IDE populares. • Ciclo completo de desarrollo – Pruebas: Con Karma para pruebas unitarias, puede saber si ha roto cosas cada vez que guarda. Y Protractor hace que tus pruebas de escenarios (E2E) se ejecuten más rápido y de manera estable. – Animación: Cree coreografías y líneas de tiempo de animación complejas y de alto rendimiento con muy poco código a través de la API intuitiva de Angular. – Accesibilidad: Cree aplicaciones accesibles con componentes compatibles con ARIA, guías para desarrolladores y una infraestructura de prueba incorporada. © JMA 2016. All rights reserved 28 Angular adopta SEMVER • • El sistema SEMVER (Semantic Versioning) es un conjunto de reglas para proporcionar un significado claro y definido a las versiones de los proyectos de software. El sistema SEMVER se compone de 3 números, siguiendo la estructura X.Y.Z, donde: – X se denomina Major: indica cambios rupturistas – Y se denomina Minor: indica cambios compatibles con la versión anterior – Z se denomina Patch: indica resoluciones de bugs (compatibles) • • Básicamente, cuando se arregla un bug se incrementa el patch, cuando se introduce una mejora se incrementa el minor y cuando se introducen cambios que no son compatibles con la versión anterior, se incrementa el major. De este modo cualquier desarrollador sabe qué esperar ante una actualización de su librería favorita. Si sale una actualización donde el major se ha incrementado, sabe que tendrá que ensuciarse las manos con el código para pasar su aplicación existente a la nueva versión. © JMA 2016. All rights reserved 29 7 Frecuencia de lanzamiento • En general, se puede esperar el siguiente ciclo de publicación: – Un lanzamiento importante (major) cada 6 meses – 1-3 lanzamientos menores para cada lanzamiento principal – El lanzamiento de un parche casi todas las semanas • Para mejorar la calidad y permitir ver lo que vendrá después, se realizan lanzamientos de versiones Beta y Release Candidatos (RC) para cada versión mayor y menor. • Dentro de la política de desaprobación, para ayudar a garantizar que se tenga tiempo suficiente y una ruta clara de actualización, se admite cada API obsoleta hasta al menos dos versiones principales posteriores, lo que significa al menos 12 meses después de la desaprobación. • Ruptura de la secuencia: – Pasa de la versión 2 → 4: – El componente Router ya estaba en una 3.xx © JMA 2016. All rights reserved 30 Novedades 4.0 • • • • • Actualización de TypeScript 2.1 Uso de StrictNullChecks de TypeScript Sintaxis if…else dentro de los templates (*ngIf) Módulo de animación separado Integración de Angular Universal como módulo de Angular Core • Mejoras de rendimiento gracias a FESM npm install @angular/common@next @angular/compiler@next @angular/compiler-cli@next @angular/core@next @angular/forms@next @angular/http@next @angular/platformbrowser@next @angular/platform-browser-dynamic@next @angular/platform-server@next @angular/router@next @angular/animations@next --save © JMA 2016. All rights reserved 31 8 Novedades 5.0 • • • • Actualización de TypeScript 2.4.2 Mejoras del compilador API Angular Universal State Transfer y soporte DOM Reconstruidos los pipes de números, fechas y monedas para mejorar la internacionalización. • Validaciones y actualizaciones de valores en `blur` o en` submit`. • Actualizado el uso de RxJS a 5.5.2 o posterior • Nuevos eventos del ciclo de vida del enrutador. npm install @angular/animations@'^5.0.0' @angular/common@'^5.0.0' @angular/compiler@'^5.0.0' @angular/compiler-cli@'^5.0.0' @angular/core@'^5.0.0' @angular/forms@'^5.0.0' @angular/http@'^5.0.0' @angular/platform-browser@'^5.0.0' @angular/platform-browser-dynamic@'^5.0.0' @angular/platformserver@'^5.0.0' @angular/router@'^5.0.0' typescript@2.4.2 rxjs@'^5.5.2' --save © JMA 2016. All rights reserved 32 Novedades 6.0 • • • • • • • • • • Lanzamiento enfocado menos en el marco subyacente, y más en la cadena de herramientas y en facilitar el movimiento rápido con Angular en el futuro, sincronizando las versiones de Angular ( @angular/core, @angular/common, @angular/compiler, etc.), Angular CLI y Angular Material + CDK. Nuevos comandos CLI: ng updatey ng add Nuevos generadores CLI: application, library, universal Angular Elements (Web Components) Angular Material + CDK Components y generadores de componentes de arranque Angular Material CLI v6 ahora es compatible con espacios de trabajo que contienen múltiples proyectos, como múltiples aplicaciones o bibliotecas. Soporte para crear y construir bibliotecas. Referenciado de proveedores en los servicios (Inyección de dependencias). Actualizada la implementación de Animaciones para que ya no necesitemos el polyfill de web animations. Angular ha sido actualizado para usar v.6 de RxJS. © JMA 2016. All rights reserved 33 9 Novedades 7.0 • Incorporación de avisos de CLI • Mejoras Rendimiento de la aplicación • Angular Material y el CDK: – Desplazamiento virtual – Arrastrar y soltar – Mejorada la Accesibilidad de selecciones • Angular Elements ahora admite la proyección de contenido • Actualización de TypeScript 3.1 • Angular ha sido actualizado para usar v.6.3 de RxJS. © JMA 2016. All rights reserved 34 Actualización • El equipo de Angular a creado la Angular Update Guide para guiar a través del proceso de actualización y para conocer los cambios que se deben realizar en el código antes de comenzar el proceso de actualización, los pasos para actualizar la aplicación y la información sobre cómo prepararse para futuras versiones de Angular. https://angular-update-guide.firebaseapp.com/ © JMA 2016. All rights reserved 35 10 TypeScript © JMA 2016. All rights reserved 50 TypeScript • • El lenguaje TypeScript fue ideado por Anders Hejlsberg – autor de Turbo Pascal, Delphi, C# y arquitecto principal de .NET- como un supraconjunto de JavaScript que permitiese utilizar tipos estáticos y otras características de los lenguajes avanzados como la Programación Orientada a Objetos. TypeScript es un lenguaje Open Source basado en JavaScript y que se integra perfectamente con otro código JavaScript, solucionando algunos de los principales problemas que tiene JavaScript: – Falta de tipado fuerte y estático. – Falta de “Syntactic Sugar” para la creación de clases – Falta de interfaces (aumenta el acoplamiento ya que obliga a programar hacia la implementación) – Módulos (parcialmente resuelto con require.js, aunque está lejos de ser perfecto) • TypeScript es un lenguaje con una sintaxis bastante parecida a la de C# y Java, por lo que es fácil aprender TypeScript para los desarrolladores con experiencia en estos lenguajes y en JavaScript. © JMA 2016. All rights reserved 51 11 TypeScript • Lo que uno programa con TypeScript, tras grabar los cambios, se convierte en JavaScript perfectamente ejecutable en todos los navegadores actuales (y antiguos), pero habremos podido: – – – – abordar desarrollos de gran complejidad, organizando el código fuente en módulos, utilizando características de auténtica orientación a objetos, y disponer de recursos de edición avanzada del código fuente (Intellisense, compleción de código, “snippets”, etc.), tanto en Visual Studio, como en otros editores populares, como Sublime Text, Eclipse, WebStorm, etc., cosa impensable hasta este momento, pero factible ahora mismo gracias a los “plug-in” de TypeScript disponibles para estos editores. © JMA 2016. All rights reserved 52 TypeScript • Amplia la sintaxis del JavaScript con la definición y comprobación de: – – – – – – Tipos básicos: booleans, number, string, Any y Void. Clases e interfaces Herencia Genéricos Módulos Anotaciones • Otra de las ventajas que otorga Typescript es que permite comunicarse con código JavaScript ya creado e incluso añadirle “tipos” a través de unos ficheros de definiciones .d.ts que indican los tipos que reciben y devuelven las funciones de una librería. © JMA 2016. All rights reserved 53 12 TypeScript • El TypeScript se traduce (“transpila”: compilar un lenguaje de alto nivel a otro de alto nivel) a JavaScript cumpliendo el estándar ECMAScript totalmente compatible con las versiones existentes. • De hecho, el “transpilador” deja elegir la versión ECMAScript del resultado, permitiendo adoptar la novedades mucho antes de que los navegadores las soporten: basta con dejar el resultado en la versión mas ampliamente difundida. • El equipo de TypeScript provee de una herramienta de línea de comandos para hacer esta compilación, se encuentra en npm y se puede instalar con el siguiente comando: – npm install -g typescript • Podemos usarlo escribiendo – tsc helloworld.ts • Los diversos “plug-in” se pueden descargar en: – https://www.typescriptlang.org © JMA 2016. All rights reserved 54 Comandos tsc • Compilación continua: – tsc –w *.ts – tsc --watch *.ts • Fichero único de salida – tsc --outFile file.js *.ts • Compilación del proyecto: -p DIRECTORY, --project DIRECTORY • Control de directorios --rootDir LOCATION Ficheros de entrada --outDir LOCATION Ficheros de salida • Directorio base de las rutas de los módulos: --baseUrl • Creación del fichero de configuración tsconfig.json: --init © JMA 2016. All rights reserved 55 13 Soportado por IDE’s/Utilidades • • • • • • • • Visual Studio 2012 … – native (+msbuild) Visual Studio Code ReSharper – included Sublime Text 2/3 – official plugin as a part of 1.5 release Online Cloud9 IDE Eclipse IDE IntelliJ IDEA Grunt, Maven, Gradle plugins © JMA 2016. All rights reserved 56 Eclipse • • • Requiere tener instalado Node.js y TypeScript Abrir Eclipse Ir a Help → Install New Software – Add the update site: http://eclipse-update.palantir.com/eclipse-typescript/ – Seleccionar e instalar TypeScript – Re arrancar Eclipse • • Opcionalmente, con el botón derecho en el proyecto seleccionar Configure → Enable TypeScript Builder En Project → Properties → Builders – – – – • Add new "Program" builder Location: ...\tsc Working Directory: ${project_loc} Arguments: --source-map --outFile build.js **/*.ts En Project → Properties → Build Automatically © JMA 2016. All rights reserved 57 14 Historia 1/2015 10/2014 v1.4 9/2014 v1.3 v1.1 6/2013 v0.9 10/2012 v0.8 4/2015 v1.5beta 4/2014 v1.0 © JMA 2016. All rights reserved 59 Compatibilidad con ES6 Feb 2015 Today (TS 1.5) https://kangax.github.io/compat-table/es6/#typescript © JMA 2016. All rights reserved 60 15 Tipos de datos • • • • • • • • • • Boolean: Number: String: Enum: var isDone: boolean = false; var height: number = 6; var name: string = "bob"; enum Color {Red, Green, Blue}; var c: Color = Color.Green; Array: var list:number[] = [1, 2, 3]; var list:Array = [1, 2, 3]; Any: var notSure: any = 4; notSure = "maybe a string instead"; notSure = false; // okay, definitely a boolean var list:any[] = [1, true, "free"]; Void: function warnUser(msg: string): void { alert(msg); } Null, Undefined, Never Object: no es number, string, boolean, symbol, null, o undefined. Clases e interfaces © JMA 2016. All rights reserved 61 Definiciones • Variables globales: • Variables locales: • Variables constantes: • Inferencia de tipo: var str: string = 'Inicio'; let x, y, z: number; // undefined const LEVEL: number = 4; let str = 'Inicio'; // string let x = 1, y = 1; // number • Tuplas: let tupla: [number, string] = [1, "cadena"]; let x : number = tupla[0]; • Alias a los tipos: type Tupla = [number, string]; let tupla: Tupla = [1, "cadena"]; © JMA 2016. All rights reserved 62 16 Sintaxis ampliada (ES6) • Cadenas (Interpolación y múltiples líneas) let msg = `El precio de ${producto} es de ${unidades * precio} euros`; • Bucle foreach: • Destructing for (var i of [10, 20, 30) { window.alert(i); } let x = 1; let y = 2; [x, y] = [y, x]; let point = {x: 1, y: 2}; {x, y} = point; • Auto nombrado: let x = 1; let y = 2; let point = {x, y}; // {x: x, y: y} © JMA 2016. All rights reserved 63 Control de tipos © JMA 2016. All rights reserved 64 17 Funciones con tipo • Tipos para los parámetros y el valor de retorno: • Opcionales y Valores por defecto: Se pueden definir valores por defecto a los parámetros en las funciones o marcarlos opcionales (undefined). function add(x: number, y: number): number { return x+y; } function(opcional?: any, valor = "foo") {...}; • Resto de los parámetros: Convierte una lista de parámetros en un array de Any. function f (x: number, y: number, ...a): number { return (x + y) * a.length } f(1, 2, "hello", true, 7) === 9 • Operador de propagación: Convierte un array o cadena en una lista de parámetros. var str = "foo" var chars = [ ...str ] // [ "f", "o", "o" ] © JMA 2016. All rights reserved 66 Expresiones Lambda Arrow functions • Funciones anónimas: let rslt = data.filter(item => item.value > 0); // equivale a: var rslt = data.filter(function (item) { return item.value > 0; }); data.forEach(elem => { console.log(elem); // … }); var fn = (num1, num2) => num1 + num2; pairs = evens.map(v => ({ even: v, odd: v + 1 })); © JMA 2016. All rights reserved 67 18 Tipos Unión © JMA 2016. All rights reserved 68 Null y Undefined (v2.1) • En TypeScript, tanto el nulo como el sin definir tienen sus propios tipos denominados undefined y null respectivamente. • Al igual que el vacío, no son muy útiles por su cuenta. let u: undefined = undefined; let N: null = null; • Por defecto, null y undefined son subtipos de todos los demás tipos, por lo que se puede asignar null o undefined a cualquier otro tipo. • Cuando se utiliza el flag --strictNullChecks, null y undefined sólo se pueden asignar a void y sus respectivos tipos. – Esto ayuda a evitar muchos errores comunes. – Si se desea pasar en un tipo o nulo o indefinido, se puede utilizar el tipo unión: tipo | null | undefined. © JMA 2016. All rights reserved 69 19 Objetos JS © JMA 2016. All rights reserved 70 Clases © JMA 2016. All rights reserved 71 20 Constructor © JMA 2016. All rights reserved 72 Compila a ES5 © JMA 2016. All rights reserved 73 21 También a ES6 © JMA 2016. All rights reserved 74 Modificadores • De acceso: – public por defecto – private – protected (a partir de 1.3) • De propiedades: – set – get • Miembros de clase: – static • Clases y miembros abstractos: – abstract • Atributos de solo lectura: – readonly (deben inicializarse en su declaración o en el constructor) © JMA 2016. All rights reserved 75 22 Propiedades class Employee { private name: string; get Name(): string { return this.name; } set Name(newName: string) { if (this.validate('Name')) { this.name = newName; this.NameChanged(); } else { // … } } // … } let employee = new Employee(); if (employee.Name === '') { employee.Name = 'Bob Smith'; } © JMA 2016. All rights reserved 77 Herencia © JMA 2016. All rights reserved 78 23 Genéricos © JMA 2016. All rights reserved 79 Interfaces © JMA 2016. All rights reserved 80 24 Interfaces: Como prototipos • Definición en línea, sin interfaces: function printLabel(labelledObj: {label: string}) { console.log(labelledObj.label); } var myObj = {size: 10, label: "Size 10 Object"}; printLabel(myObj); • Usando interfaces: interface LabelledValue { label: string; } function printLabel(labelledObj: LabelledValue) { console.log(labelledObj.label); } var myObj = {size: 10, label: "Size 10 Object"}; printLabel(myObj); © JMA 2016. All rights reserved 81 Interfaces: Propiedades opcionales interface SquareConfig { color?: string; width?: number; } function createSquare(config: SquareConfig): {color: string; area: number} { var newSquare = {color: "white", area: 100}; if (config.color) { newSquare.color = config.color; } if (config.width) { newSquare.area = config.width * config.width; } return newSquare; } var mySquare = createSquare({color: "black"}); © JMA 2016. All rights reserved 82 25 Interfaces: Funciones y Arrays • Prototipos de Funciones interface SearchFunc { (source: string, subString: string): boolean; } var mySearch: SearchFunc; mySearch = function(source: string, subStr: string) { var result = source.search(subStr); return result != -1; } • Prototipos de Arrays interface StringArray { [index: number]: string; } var myArray: StringArray; myArray = ["Bob", "Fred"]; © JMA 2016. All rights reserved 83 Módulos © JMA 2016. All rights reserved 84 26 Módulos (ES6) • Ficheros como módulos: – Solo se puede importar lo previamente exportado. – Es necesario importar antes de utilizar – El fichero en el from sin extensión y ruta relativa (./ ../) o sin ruta (NODE_MODULES) • Exportar: export public class MyClass { } export { MY_CONST, myFunction, name as otherName } • Importar: import * from './my_module'; import * as MyModule from './my_module'; import { MyClass, MY_CONST, myFunction as func } from './my_module'; • Pasarelas: Importar y exportar (index.ts) export { MyClass, MY_CONST, myFunction as func } from './my_module'; © JMA 2016. All rights reserved 85 Decoradores (ES7) © JMA 2016. All rights reserved 87 27 Compatibilidad con Frameworks JS • Ya existen ficheros de definiciones (.d.ts) para la mayoría de los framework mas populares (http://definitelytyped.org/). – npm install --save-dev @types/jquery • Definiciones: https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types © JMA 2016. All rights reserved 88 Angular 2.0 – Escrito en TypeScript © JMA 2016. All rights reserved 89 28 ARQUITECTURA DE ANGULAR © JMA 2016. All rights reserved 134 Arquitectura de Angular © JMA 2016. All rights reserved 137 29 Módulo • La aplicaciones Angular son modulares. • Angular dispone de su propio sistema de modularidad llamado módulos Angular o NgModules . • Cada aplicación Angular tiene al menos un módulo, el módulo raíz, convencionalmente denominado AppModule. • Mientras que el módulo de raíz puede ser el único módulo en una aplicación pequeña, en la mayoría de las aplicaciones existirán muchos más “módulos de características”, cada uno como un bloque coherente de código dedicado a un dominio de aplicación, un flujo de trabajo o un conjunto estrechamente relacionado de capacidades. • El módulo Angular, una clase decorada con @NgModule, es una característica fundamental de Angular. © JMA 2016. All rights reserved 138 Bibliotecas Angular • Los contenedores Angular son una colección de módulos de JavaScript, se puede pensar en ellos como módulos de biblioteca. • Cada nombre de la biblioteca Angular comienza con el prefijo @angular. • Se pueden instalar con el gestor de paquetes NPM e importar partes de ellos con instrucciones import del JavaScript. • De esta manera se está utilizando tanto los sistemas de módulos de Angular como los de JavaScript juntos. © JMA 2016. All rights reserved 139 30 Módulos Angular vs. Módulos JavaScript(ES6)/TypeScript • JavaScript tiene su propio sistema de módulos para la gestión de colecciones de objetos de JavaScript. • Es completamente diferente y sin relación con el sistema de módulos Angular. • En JavaScript cada archivo es un módulo y todos los objetos definidos en el archivo pertenece a ese módulo. • El módulo declara algunos objetos para ser públicos marcándolas con la palabra clave export. • Los módulos de JavaScript usan declaraciones de importación para tener acceso a los objetos públicos (exportados) de dichos módulos. • Se trata de dos sistemas diferentes y complementarios de módulos. © JMA 2016. All rights reserved 140 Metadatos • Angular ha optado por sistema declarativo de definición de sus elementos mediante el uso de decoradores (ES7), también conocidos como anotaciones o metadatos. • Los Decoradores son funciones que modifican las clases de JavaScript. • Angular suministra decoradores que anotan a las clases con metadatos y le indican lo que significan dichas clases y cómo debe trabajar con ellas. @NgModule({ imports: [ BrowserModule ], declarations: [ AppComponent ], exports: [ AppComponent ], bootstrap: [ AppComponent ] }) export class AppModule { } © JMA 2016. All rights reserved 141 31 Componentes • Un componente controla una parte de la pantalla denomina vista. • Se puede considerar que un componte es una clase con interfaz de usuario. • Reúne en un único elemento: el código (clase que expone datos y funcionalidad), su representación (plantilla) y su estética (CSS). • El código interactúa con la plantilla a través del enlazado dinámico. • Una vez creado, un componente es como una nueva etiqueta HTML que puede ser utilizada en otras plantillas. • Los componentes son elementos estancos que establecen una frontera clara y concisa de entrada/salida. • Angular crea, actualiza y destruye los componentes según el usuario se mueve a través de la aplicación. • Angular permite personalizar mediante el uso de enganches (hooks) lo que pasa en cada fase del ciclo de vida del componente. © JMA 2016. All rights reserved 142 Plantillas • • • Las plantillas contienen la representación visual de los componentes. Son segmentos escritos en HTML ampliado con elementos suministrados por Angular como las directivas, marcadores, pipes, … Cuentan con la lógica de presentación pero no permiten la codificación: los datos y la funcionalidad se los suministra la clase del componente. Una plantilla puede utilizar otros componentes, actuan como contenedores, dichos componentes pueden contener a su vez otros componentes. Esto crea un árbol de componentes: el modelo de composición. © JMA 2016. All rights reserved 143 32 Enlace de datos • Automatiza, de una forma declarativa, la comunicación entre los controles HTML de la plantilla y las propiedades y métodos del código del componente. • Requieren un nuevo modelo mental declarativo frente al imperativo tradicional. • El enlace de datos también permite la comunicación entre los componentes principales y secundarios. © JMA 2016. All rights reserved 144 Enlace de datos • La comunicación ente Componente y Plantilla puede ser: – Unidireccional: • Datos (C→P) – Interpolación – Propiedades • Comandos (P→C) – Eventos – Bidireccional: • Datos (P→C) – Directivas © JMA 2016. All rights reserved 145 33 Directivas • Las directivas son marcas en los elementos del árbol DOM, en los nodos del HTML, que indican al Angular que debe asignar cierto comportamiento a dichos elementos o transformarlos según corresponda. • Podríamos decir que las directivas nos permiten añadir comportamiento dinámico al árbol DOM, haciendo uso de las directivas propias del Angular o extender la funcionalidad hasta donde necesitemos creando las nuestras propias. • La recomendación es que el único sitio donde se puede manipular el árbol DOM debe ser en las directivas, para que entre dentro del ciclo de vida de compilación, binding y renderización del HTML que sigue el Angular. • Aunque un componente es técnicamente una directiva-conplantilla, conceptualmente son dos elementos completamente diferentes. © JMA 2016. All rights reserved 146 Pipes • El resultado de una expresión puede requerir alguna transformación antes de estar listo para mostrarla en pantalla: mostrar un número como moneda, que el texto pase a mayúsculas o filtrar una lista y ordenarla. • Los Pipes de Angular, anteriormente denominados filtros, son simples funciones que aceptan un valor de entrada y devuelven un valor transformado. Son fáciles de aplicar dentro de expresiones de plantilla, usando el operador tubería (|). • Son una buena opción para las pequeñas transformaciones, dado que al ser encadenables un conjunto de transformaciones pequeñas pueden permitir una transformación compleja. © JMA 2016. All rights reserved 147 34 Servicios • Los servicios en Angular son una categoría muy amplia que abarca cualquier valor, función o característica que necesita una aplicación. • Casi cualquier cosa puede ser un servicio, aunque típicamente es una clase con un propósito limitado y bien definido, que debe hacer algo específico y hacerlo bien. • Angular no tiene una definición especifica para los servicios, no hay una clase base o anotación, ni un lugar para registrarlos. • Los servicios son fundamentales para cualquier aplicación Angular y los componentes son grandes consumidores de servicios. • La responsabilidad de un componente es implementar la experiencia de los usuarios y nada más: expone propiedades y métodos para el enlace desde la plantilla, y delega todo lo demás en las directivas (manipulación del DOM) y los servicios (lógica de negocio). © JMA 2016. All rights reserved 148 Inyección de dependencia • • • • • La Inyección de Dependencias (DI) es un mecanismo que proporciona nuevas instancias de una clase con todas las dependencias que requiere plenamente formadas. La mayoría de dependencias son servicios, y Angular usa la DI para proporcionar nuevos componentes con los servicios ya instanciados que necesitan. Gracias a TypeScript, Angular sabe de qué servicios depende un componente con tan solo mirar su constructor. El Injector es el principal mecanismo detrás de la DI. A nivel interno, un inyector dispone de un contenedor con las instancias de servicios que crea él mismo. Si una instancia no está en el contenedor, el inyector crea una nueva y la añade al contenedor antes de devolver el servicio a Angular, por eso los servicios son singletons en el ámbito de su inyector. El provider es cualquier cosa que puede crear o devolver un servicio, típicamente, la propia clase que define el servicio. Los providers pueden registrarse en cualquier nivel del árbol de componentes de la aplicación a través de los metadatos de componentes. © JMA 2016. All rights reserved 149 35 Web Components • • • Los Web Components nos ofrecen un estándar que va enfocado a la creación de todo tipo de componentes utilizables en una página web, para realizar interfaces de usuario y elementos que nos permitan presentar información (o sea, son tecnologías que se desarrollan en el lado del cliente). Los propios desarrolladores serán los que puedan, en base a las herramientas que incluye Web Components crear esos nuevos elementos y publicarlos para que otras personas también los puedan usar. Los Web Components son una reciente incorporación al HTML5 que, si siguen evolucionando al ritmo al que lo están haciendo, pueden suponer el mayor cambio en el mundo web en años y solucionar de golpe varios problemas históricos de HTML. El estándar, en proceso de definición, en realidad, se compone de 4 subelementos complementarios, pero independientes entre si: – – – – • Custom Elements http://w3c.github.io/webcomponents/spec/custom/ Templates https://www.w3.org/TR/html5/scripting-1.html#the-template-element Shadow DOM https://www.w3.org/TR/shadow-dom/ HTML Imports http://w3c.github.io/webcomponents/spec/imports/ Cualquiera de ellos puede ser usado por separado, lo que hace que la tecnología de los Web Elements sea, además de muy útil, muy flexible. © JMA 2016. All rights reserved 152 Web Components • Templates: son fragmentos de HTML que representan al componente de modo que cuando se haga referencia al componente se usará esta plantilla. • HTML Import: es la posibilidad de incluir un HTML dentro de otro mediante un tag . De este modo el template de un Web Component formará parte del otro. • Shadow DOM: permite encapsular el subarbol DOM de un componente, de modo que la interacción desde fuera y hacia dentro está controlada. Es importante para que los componentes no entren en conflictos al formar parte de la misma página. • Custom Elements: para la definición de Tags específicos que representan a los web components que se han creado. © JMA 2016. All rights reserved 153 36 Angular Elements • • • • Los Angular Elements son componentes Angular empaquetados como Web Components, también conocidos como elementos personalizados, el estándar web para definir nuevos elementos HTML de una forma independiente del framework. Los Web Components son una característica de la Plataforma Web actualmente compatible con las últimas versiones Chrome, Opera y Safari, y están disponibles para otros navegadores a través de polyfills. Un elemento personalizado extiende HTML al permitir definir una etiqueta cuyo contenido está creado y controlado por código JavaScript. El navegador mantiene una serie CustomElementRegistry de elementos personalizados definidos (o componentes web), que asigna una clase de JavaScript instanciable a una etiqueta HTML. El paquete @angular/elements exporta una API createCustomElement() que proporciona un puente desde la interfaz de componente y la funcionalidad de detección de cambios de Angular a la API DOM integrada. Transformar un componente en un elemento personalizado hace que toda la infraestructura Angular requerida esté disponible para el navegador. La creación de un elemento personalizado es simple y directa, y conecta automáticamente la vista definida por el componente con la detección de cambios y el enlace de datos, asignando la funcionalidad Angular a los equivalentes de HTML nativos correspondientes. © JMA 2016. All rights reserved 154 Model View ViewModel (MVVM) • El Modelo es la entidad que representa el concepto de negocio. • La Vista es la representación gráfica del control o un conjunto de controles que muestran el Modelo de datos en pantalla. • La VistaModelo es la que une todo. Contiene la lógica del interfaz de usuario, los comandos, los eventos y una referencia al Modelo. Eventos Vista Métodos Eventos VistaModelo Métodos Modelo Data Binding Comandos © JMA 2016. All rights reserved 155 37 Soporte de navegador Navegador Versiones compatibles Chrome Última Firefox Última Edge Últimas 2 versiones IE 11, 10, 9 IE Mobile 11 Safari Últimas 2 versiones iOS Últimas 2 versiones Android Nougat (7.0) Marshmallow (6.0) Lollipop (5.0, 5.1) KitKat (4.4) © JMA 2016. All rights reserved 156 HERRAMIENTAS DE DESARROLLO © JMA 2016. All rights reserved 157 38 IDEs • Visual Studio Code - http://code.visualstudio.com/ – VS Code is a Free, Lightweight Tool for Editing and Debugging Web Apps. • StackBlitz - https://stackblitz.com – The online IDE for web applications. Powered by VS Code and GitHub. • Angular IDE by Webclipse https://www.genuitec.com/products/angular-ide – Built first and foremost for Angular. Turnkey setup for beginners; powerful for experts. • IntelliJ IDEA - https://www.jetbrains.com/idea/ – Capable and Ergonomic Java * IDE • Webstorm - https://www.jetbrains.com/webstorm/ – Lightweight yet powerful IDE, perfectly equipped for complex clientside development and server-side development with Node.js © JMA 2016. All rights reserved 158 Instalación de utilidades Consideraciones previas – Las utilidades son de línea de comandos. – Para ejecutar los comandos es necesario abrir la consola comandos (Símbolo del sistema) – Siempre que se realice una instalación o creación es conveniente “Ejecutar como Administrador” para evitar otros problemas. – En algunos casos el firewall de Windows, la configuración del proxy y las aplicaciones antivirus pueden dar problemas. GIT: Software de control de versiones – Descargar e instalar: https://git-scm.com/ – Verificar desde consola de comandos: • git Node.js: Entorno en tiempo de ejecución – Descargar e instalar: https://nodejs.org – Verificar desde consola de comandos: • node --version © JMA 2016. All rights reserved 159 39 npm: Node Package Manager • Aunque se instala con el Node es conveniente actualizarlo: • Verificar desde consola de comandos: • Configuración: – npm update -g npm – npm --version – npm config edit – proxy=http://usr:pwd@proxy.dominion.com:8080 Símbolos: %HEX ASCII • Generar fichero de dependencias package.json: • Instalación de paquetes: – npm init – npm install -g grunt-cli grunt-init karma karma-cli Global (CLI) – npm install jasmine-core tslint --save --save-dev – npm install Dependencias en package.json • Arranque del servidor: – npm start © JMA 2016. All rights reserved 160 Generación del esqueleto de aplicación • Configurar un nuevo proyecto de Angular 2 es un proceso complicado y tedioso, con tareas como: – Crear la estructura básica de archivos y bootstrap – Configurar SystemJS o WebPack para transpilar el código – Crear scripts para ejecutar el servidor de desarrollo, tester, publicación, … • Disponemos de diferentes opciones de asistencia: – Proyectos semilla (seed) disponibles en github – Generadores basados en Yeoman – Herramienta oficial de gestión de proyectos, Angular CLI. • Angular CLI, creada por el equipo de Angular, es una Command Line Interface que permite generar proyectos y plantillas de código desde consola, así como ejecutar un servidor de desarrollo o lanzar los tests de la aplicación. (https://cli.angular.io/) – npm install -g @angular/cli@latest © JMA 2016. All rights reserved 161 40 Proyectos semilla • Proyectos semilla: – – – – – – – • https://github.com/angular/quickstart http://mgechev.github.io/angular2-seed https://github.com/ghpabs/angular2-seed-project https://github.com/cureon/angular2-sass-gulp-boilerplate https://angularclass.github.io/angular2-webpack-starter https://github.com/LuxDie/angular2-seed-jade https://github.com/justindujardin/angular2-seed Generadores de código basados en Yeoman (http://yeoman.io/generators): – https://github.com/FountainJS/generator-fountain-angular2 – https://github.com/ericmdantas/generator-ng-fullstack • NOTA: Es conveniente verificar si están actualizados a la última versión de Angular 2, pueden estar desactualizados. © JMA 2016. All rights reserved 162 Creación y puesta en marcha • Acceso al listado de comandos y opciones – $ ng help • Nuevo proyecto – $ ng new myApp – Esto creará la carpeta myApp con un esqueleto de proyecto ya montado según la última versión de Angular y todo el trabajo sucio de configuración de WebPack para transpilar el código y generar un bundle, configuración de tests, lint y typescript, etc. – Además, instala todas las dependencias necesarias de npm e incluso inicializa el proyecto como un repositorio de GIT. • Servidor de desarrollo – ng serve – Esto lanza tu app en la URL http://localhost:4200 y actualiza el contenido cada vez que guardas algún cambio. © JMA 2016. All rights reserved 163 41 Generar código • • Hay elementos de código que mantienen una cierta estructura y no necesitas escribirla cada vez que creas un archivo nuevo. El comando generate permite generar algunos de los elementos habituales en Angular. – – – – – – – – – Componentes: Directivas: Pipe: Servicios: Clases: Interface: Enumerados: Módulos: Guardian (rutas): --module my-module --project my-lib ng generate component my-new-component ng g directive my-new-directive ng g pipe my-new-pipe ng g service my-new-service ng g class my-new-class ng g interface my-new-interface ng g enum my-new-enum ng g module my-module ng generate guard my-guard Indica el modulo si no es el principal Indica el proyecto si no es el principal © JMA 2016. All rights reserved 164 Schematics en Angular CLI (v.6) • Schematics es una herramienta de flujo de trabajo para la web moderna; permite aplicar transformaciones al proyecto, como crear un nuevo componente, actualizar el código para corregir cambios importantes en una dependencia, agregar una nueva opción o marco de configuración a un proyecto existente. • Generadores de componentes de arranque Angular Material: – Un componente de inicio que incluye una barra de herramientas con el nombre de la aplicación y la navegación lateral: • ng generate @angular/material:material-nav --name=my-nav – Un componente de panel de inicio que contenga una lista de tarjetas de cuadrícula dinámica: • ng generate @angular/material:material-dashboard --name=my-dashboard – Un componente de tabla de datos de inicio que está pre configurado con un datasource para ordenar y paginar: • ng generate @angular/material:material-table --name=my-table © JMA 2016. All rights reserved 166 42 Nuevos comandos (v.6) • ng update analiza el package.json de la aplicación actual y utiliza la heurísticas de Angular para recomendar y realizar las actualizaciones que necesita la aplicación. – npm install -g @angular/cli – npm install @angular/cli – ng update @angular/cli • ng add permite agregar nuevas capacidades al proyecto y puede actualizar el proyecto con cambios de configuración, agregar dependencias adicionales o estructurar el código de inicialización específico del paquete. – ng add @angular/pwa - Convierte la aplicación en un PWA agregando un manifiesto de aplicación y un service worker. – ng add @ng-bootstrap/schematics - Agrega ng-bootstrap a la aplicación. – ng add @angular/material - Instala y configura Angular Material y el estilo, y registrar nuevos componentes de inicio en ng generate. – ng add @angular/elements - Agrega el polyfill document-register-element.js y las dependencias necesarios para los Angular Elements. © JMA 2016. All rights reserved 167 Pruebas • Son imprescindibles en entornos de calidad: permite ejecutar las pruebas unitarias, las pruebas de extremo a extremo o comprobar la sintaxis. • Para comprobar la sintaxis: Puedes ejecutar el analizador con el comando: – ng lint • Para ejecutar tests unitarios: Puedes lanzar los tests unitarios con karma con el comando: – ng test • Para ejecutar tests e2e: Puedes lanzar los tests end to end con protractor con el comando: – ng e2e © JMA 2016. All rights reserved 168 43 Despliegue • Construye la aplicación en la carpeta /dist – ng build – ng build --dev • Paso a producción, construye optimizándolo todo para producción – ng build --prod – ng build --prod --env=prod – ng build --target=production --environment=prod • Precompila la aplicación – ng build --prod --aot © JMA 2016. All rights reserved 169 Estructura de directorios de soporte src e2e app.e2e-spec.ts app.po.ts tsconfig.json .editorconfig .gitignore angular.json karma.conf.js package.json protractor.conf.js README.md tsconfig.json tslint.json • src: Fuentes de la aplicación • e2e: Test end to end • Ficheros de configuración de librerías y herramientas • Posteriormente aparecerán los siguientes directorios: – node_modules: Librerías y herramientas descargadas – dist: Resultado para publicar en el servidor web – coverage: Informes de cobertura de código © JMA 2016. All rights reserved 171 44 Estructura de directorios de aplicación • app app.component.css app.component.html app.component.spec.ts app.component.ts app.module.ts index.ts assets environments environment.prod.ts environment.ts favicon.ico index.html main.ts polyfills.ts styles.css test.ts tsconfig.app.json tsconfig.spec.json typings.d.ts • • • • • • • • • app: Carpeta que contiene los ficheros fuente principales de la aplicación. assets: Carpeta con los recursos que se copiaran a la carpeta build. environments: configuración de los diferentes entornos. main.ts: Arranque del módulo principal de la aplicación. No es necesario modificarle. favicon.ico: Icono para el navegador. index.html: Página principal (SPA). style.css: Se editará para incluir CSS global de la web, se concatena, minimiza y enlaza en index.html automáticamente. test.ts: pruebas del arranque. polyfills.js: importación de los diferentes módulos de compatibilidad ES6 y ES7. Tsconfig.xxxx.json: Configuración del compilador TypeScript para la aplicación y las pruebas. © JMA 2016. All rights reserved 172 Webpack • Webpack (https://webpack.github.io/) es un empaquetador de módulos, es decir, permite generar un archivo único con todos aquellos módulos que necesita la aplicación para funcionar. • Toma módulos con dependencias y genera archivos estáticos correspondientes a dichos módulos. • Webpack va mas allá y se ha convertido en una herramienta muy versátil. Entre otras cosas, destaca que: – Puede generar solo aquellos fragmentos de JS que realmente necesita cada página. • Dividir el árbol de dependencias en trozos cargados bajo demanda • Haciendo más rápida la carga inicial – Tiene varios loaders para importar y empaquetar también otros recursos (CSS, templates, …) así como otros lenguajes (ES6 con Babel, TypeScript, SaSS, etc). – Sus plugins permiten hacer otras tareas importantes como por ejemplo minimizar y ofuscar el código. © JMA 2016. All rights reserved 174 45 Librerías de terceros • Descargar • Referenciar código en angular.json – npm install bootstrap --save "scripts": [ "node_modules/jquery/dist/jquery.js", {"input": "./node_modules/bootstrap/dist/js/bootstrap.js"}, ] • Referenciar estilos en angular.json "styles": [ {"input": "./node_modules/bootstrap/dist/css/bootstrap.css"}, "styles.css" ] • Inclusión de ficheros: "assets": [ "src/assets", "src/favicon.ico", { "glob": "**/*", "input": "./node_modules/bootstrap/dist/font", "output": "/" } ], © JMA 2016. All rights reserved 177 Glifos • Font Awesome (https://fontawesome.com/) • Instalar: npm install --save @fortawesome/fontawesome-free • Configurar en angular.json "build": { "options": { "styles": [ "node_modules/@fortawesome/fontawesome-free/css/all.css" "styles.css" ], } } • Probar: {{title}}
© JMA 2016. All rights reserved 178 46 GIT • Preséntate a Git – git config --global user.name "Your Name Here“ – git config --global user.email your_email@youremail.com • Crea un repositorio central • Conecta con el repositorio remoto – https://github.com/ – git remote add origin https://github.com/username/myproject.git – git push -u origin master • Actualiza el repositorio con los cambios: – git commit -m "first commit" – git push • Para clonar el repositorio: • Para obtener las últimas modificaciones: – git clone https://github.com/username/myproject.git local-dir – git pull © JMA 2016. All rights reserved 179 MÓDULOS © JMA 2016. All rights reserved 180 47 Módulos • • • • • • Los módulos son una buena manera de organizar la aplicación y extenderla con las capacidades de las bibliotecas externas. Los módulos Angular consolidan componentes, directivas y pipes en bloques cohesivos de funcionalidad, cada uno centrado en un área de características, un dominio de negocio de la aplicación, un flujo de trabajo o una colección común de los servicios públicos. Los módulos pueden añadir servicios a la aplicación, que pueden ser desarrollados internamente, tales como el registrador de aplicación, o pueden provenir de fuentes externas, tales como el enrutador de Angular y el cliente HTTP. Muchas bibliotecas de Angular son módulos (por ejemplo: FormsModule, HttpModule, RouterModule). Muchas bibliotecas de terceros están disponibles como módulos Angular (por ejemplo: Bootstrap, Material Design, Ionic, AngularFire2 ). Los módulos pueden ser cargados cuando se inicia la aplicación o de forma asíncrona por el router. © JMA 2016. All rights reserved 181 Módulo • Un módulo Angular es una clase adornada con la función decoradora @NgModule: objeto de metadatos que indica cómo Angular compila y ejecuta código del módulo. – Declara qué componentes, directivas y pipes pertenecen al módulo. – Expone algunos de ellos de manera pública para que puedan ser usados externamente por otras plantillas. – Importar otros módulos con los componentes, las directivas y las pipes necesarios para los componentes de este módulo. – Se pueden agregar proveedores de servicios a los inyectores de dependencia de aplicación que cualquier componente de la aplicación podrá utilizar. • • • Cada aplicación Angular tiene al menos un módulo, el módulo raíz, convencionalmente denominado AppModule. Es el responsable del arranque (Bootstrap) de la aplicación. El módulo principal es todo lo que se necesita en una aplicación sencilla con unos pocos componentes. A medida que crece la aplicación, se refactoriza el módulo raíz en módulos de características, los cuales representan colecciones de funcionalidad relacionada, que luego se importan al módulo de raíz . © JMA 2016. All rights reserved 182 48 @NgModule import { NgModule } from '@angular/core'; • imports: Especifica una lista de módulos cuyos componentes / directivas / pipes deben estar disponibles para las plantillas de este módulo. • declarations: Especifica una lista de componentes / directivas / pipes que pertenecen a este módulo (son privadas al módulo si no se exportan). • providers: Define el conjunto de objetos inyectables que están disponibles en el inyector de este módulo. • exports: Especifica una lista de componentes / directivas / pipes que se pueden utilizar dentro de las plantilla de cualquier componente que importe este módulo Angular. • bootstrap: Define los componentes que deben ser arrancados cuando se arranque el módulo, se añadirán automáticamente a entryComponents. © JMA 2016. All rights reserved 183 Módulo de raíz import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { AppComponent } from './app.component'; @NgModule({ imports: [ BrowserModule ], declarations: [ AppComponent ], bootstrap: [ AppComponent ] }) export class AppModule { } • BrowserModule: módulo necesario para las aplicaciones de navegador. – – Registra los proveedores de servicios de aplicaciones críticas. También incluye directivas/pipes comunes como NgIf y NgFor que se convierten inmediatamente en visibles y utilizables por cualquiera de las plantillas de los componentes del módulo. © JMA 2016. All rights reserved 184 49 Módulos TypeScript/JavaScript(ES6) • No confundir con los módulos de Angular. • Es necesario importar todas las clases, funciones, … que se vayan a utilizar en el código: import { Component, OnInit } from '@angular/core'; import { AppComponent } from './app.component'; • Se pueden importar todos los elementos del módulo {*} aunque no suele ser recomendable. • Hay que referenciar la ruta relativa al fichero del módulo sin extensión. • Para poder importar algo es necesario haberlo marcado previamente como importable con export. export class AppComponent { © JMA 2016. All rights reserved 185 Módulos de características • Generar el módulo: • Importar CommonModule en vez de BrowserModule • • Implementar los diferentes elementos del módulo Exportar lo elementos compartidos: ng generate module myCore import { CommonModule } from '@angular/common'; @NgModule({ // … exports: [MyCoreComponent, MyCorePipe] }) export class MyCoreModule { } • Importar el módulo: import { MyCoreModule } from './my-core/my-core.module'; @NgModule({ //… imports: [ //… MyCoreModule] }) export class AppModule { } • Utilizar las nuevas características obtenidas. © JMA 2016. All rights reserved 186 50 Módulos de características • Hay cinco categorías generales de módulos de características que tienden a pertenecer a los siguientes grupos: – Módulos de características de dominio: ofrecen una experiencia de usuario dedicada a un dominio de aplicación particular, exponen el componente superior y ocultan los subcomponentes. – Módulos de características enrutados: los componentes principales son los objetivos de las rutas de navegación del enrutador. – Módulos de enrutamiento: proporciona la configuración de enrutamiento para otro módulo y separa las preocupaciones de enrutamiento de su módulo complementario. – Módulos de características del servicio: brindan servicios de utilidad como acceso a datos y mensajería. – Módulos de características de widgets: hace que los componentes, las directivas y los pipes estén disponibles para los módulos externos (bibliotecas de componentes de UI) © JMA 2016. All rights reserved 187 Prevenir la reimportación • • Hay módulos que solo se deben importar en el módulo raíz y una sola vez. Para prevenir la reimportación es necesario crear el siguiente constructor en el módulo: constructor (@Optional() @SkipSelf() parentModule: MyCoreModule) { if (parentModule) { throw new Error( 'MyCoreModule is already loaded. Import it in the AppModule only'); } } • • La inyección podría ser circular si Angular busca MyCoreModule en el inyector actual. El decorador @SkipSelf significa “buscar MyCoreModule en un inyector antecesor, por encima de mí en la jerarquía del inyector“. Si el inyecto no lo encuentra, como debería ser, suministrará un null al constructor. El decorador @Optional permite que el constructor no reciba el parámetro. © JMA 2016. All rights reserved 188 51 Arranque de la aplicación (v4) // main.ts import { enableProdMode } from '@angular/core'; import { platformBrowserDynamic } from '@angular/platformbrowser-dynamic'; import { AppModule } from './app/app.module'; import { environment } from './environments/environment'; if (environment.production) { enableProdMode(); } platformBrowserDynamic().bootstrapModule(AppModule); © JMA 2016. All rights reserved 190 SPA (v4)Curso de Angular2 © JMA 2016. All rights reserved 192 52 Módulos usados frecuentemente NgModule Importar desde Por qué lo usas BrowserModule @angular/platform-browser Para ejecutar la aplicación en un navegador CommonModule @angular/common Para usar directivas comunes como NgIf y NgFor FormsModule @angular/forms Cuando crea formularios controlados por plantilla (incluye NgModel) ReactiveFormsModule @angular/forms Al construir formularios reactivos RouterModule @angular/router Para enrutamiento y cuando se quiere utilizar RouterLink, .forRoot() y .forChild() HttpClientModule @angular/common/http Para acceder a un servidor © JMA 2016. All rights reserved 193 SERVICIOS © JMA 2016. All rights reserved 194 53 Servicios • Los servicios en Angular es una categoría muy amplia que abarca cualquier valor, función o característica que necesita una aplicación. • Angular no tiene una definición especifica para los servicios, no hay una clase base ni un lugar para registrarlos, son simples Clases. • Tienen la siguiente particularidad: – @Injectable: Este decorador avisa a Angular de que el servicio espera utilizar otros servicios y genera los metadatos que necesita el servicio para detectar la Inyección de Dependencias (DI) en el constructor. No es obligatorio ponerlo si el servicio no tiene IoC de otros servicios, pero es recomendable para evitar errores si en el futuro se añade alguna dependencia. – Dependency Injection (DI) en el Constructor: Aquí aprovechamos las bondades de TypeScript para pasar explícitamente un objeto con tipo en el constructor. De este modo, Angular es capaz de inferir la Inyección de Dependencias. © JMA 2016. All rights reserved 195 Servicio ng generate service datos import {Injectable} from '@angular/core'; import { Logger } from '../core/logger.service'; @Injectable() export class DatosService { modelo = {}; constructor(public logger: Logger){} metodo1() { … } metodo2() { … } } © JMA 2016. All rights reserved 196 54 Inyección de dependencia • • • • • La Inyección de Dependencias (DI) es un mecanismo que proporciona nuevas instancias de una clase con todas las dependencias que requiere plenamente formadas. La mayoría de dependencias son servicios, y Angular usa la DI para proporcionar nuevos componentes con los servicios ya instanciados que necesitan. Gracias a TypeScript, Angular sabe de qué servicios depende un componente con tan solo mirar su constructor. El Injector es el principal mecanismo detrás de la DI. A nivel interno, un inyector dispone de un contenedor con las instancias de servicios que crea él mismo. Si una instancia no está en el contenedor, el inyector crea una nueva y la añade al contenedor antes de devolver el servicio a Angular, por eso se dice que los servicios son singletons en el ámbito de su inyector. El provider es cualquier cosa que puede crear o devolver un servicio, como la propia clase que define el servicio. Los providers pueden registrarse en cualquier nivel del árbol de componentes de la aplicación a través de los metadatos de componentes. © JMA 2016. All rights reserved 197 Registrar en el inyector • Globalmente, único para todo el módulo: import { DatosService } from './datos.service'; @NgModule({ … providers: [DatosService, Logger], … }) export class AppModule { } • En el componente, solo estará disponibles para el componente y su contenido: import { DatosService } from './datos.service'; @Component({ … providers: [DatosService, Logger], … }) export class AppComponent { © JMA 2016. All rights reserved 198 55 Proveedores • Un proveedor proporciona la versión concreta en tiempo de ejecución de un valor de dependencia. El inyector se basa en los proveedores para crear instancias de los servicios que inyecta en componentes y otros servicios. • Proveedor simplificado: providers: [MyService] • Proveedor de objeto literal: providers:[{ provide: alias, useClass: MyService}] • Una instancia para dos proveedores: providers: [ NewLogger, { provide: OldLogger, useExisting: NewLogger}] • Añadir a un proveedor múltiple: { provide: NG_VALIDATORS, useExisting: MyDirective, multi: true } • Proveedor de valor ya instanciado: { provide: VERSION, useValue: '2.1.0.234' }] © JMA 2016. All rights reserved 199 Factorías • • A veces tenemos que crear el valor dependiente dinámicamente, en base a información que no tendremos hasta el último momento posible. Tal vez la información cambia varias veces en el transcurso de la sesión de navegación. Supongamos también que el servicio inyectable no tiene acceso independiente a la fuente de esta información. Esta situación requiere de un proveedor factoría: función que genera la instancia del servicio. export class DatosService { constructor(logger: Logger, isAuthorized: boolean){} // … } export let DatosServiceFactory = (logger: Logger, userService: UserService) => { return new DatosService(logger, userService.user.isAuthorized); }; providers: [{provide: DatosService, useFactory: DatosServiceFactory, deps: [Logger, UserService] }] © JMA 2016. All rights reserved 200 56 Auto referenciado de proveedores (v.6) • Se puede especificar que el servicio debe proporcionarse en el inyector raíz: agrega un proveedor del servicio al inyector del módulo principal, estos proveedores están disponibles para todas las clases en la aplicación, siempre que tengan el token de búsqueda. @Injectable({ providedIn: 'root', }) • También es posible especificar que se debe proporcionar un módulo en particular: @Injectable({ providedIn: MyCoreModule, }) • Dan a Angular la capacidad de eliminar servicios del producto final que no se usan en su aplicación. © JMA 2016. All rights reserved 201 Dependencias que no son de clase • La inyección utiliza los nombres de las clase. A veces se quiere inyectar algo que no tiene una representación en tiempo de ejecución: interfaces, genéricos, arrays, … • En dichos casos es necesario crear una cadena o un token y referenciar con el decorador @Inject. • Mediante cadenas: providers: [{ provide: 'VERSION', useValue: '2.1.0.234' }] constructor(@Inject('VERSION') public version: string) • InjectionToken permite crear un token que se puede utilizar en un proveedor de DI, donde T que es el tipo de objeto que será devuelto por el Inyector. Esto proporciona un nivel adicional de seguridad de tipo. export const VERSION = new InjectionToken ('Version'); providers: [{ provide: VERSION, useValue: '2.1.0.234' }] constructor(@Inject(VERSION) public version: string) © JMA 2016. All rights reserved 202 57 Dependencias opcionales • Se puede indicar que se inyecte solo si existe la clase del servicio: import { Optional } from '@angular/core'; class AnotherService{ constructor(@Optional() private logger: Logger) { if (this.logger) { this.logger.log("I can log!!"); } } } • Es importante que el componente o servicio este preparado para que su dependencia tenga valor null. © JMA 2016. All rights reserved 203 Inyectores Explícitos • Habitualmente no tenemos que crear los inyectores en Angular, dado que se crea automáticamente un inyector a nivel del módulo para toda la aplicación durante el proceso de arranque. • Los componentes cuentan con sus propios inyectores. • Se puede crear un inyector de forma explicita: – injector = Injector.create([Http, Logger]); • Para posteriormente obtener instancias inyectadas: – let srv= injector.get(Logger); • Las dependencias son únicas dentro del alcance de un inyector, sin embargo, al ser Angular DI un sistema de inyección jerárquica, los inyectores anidados pueden crear sus propias instancias de servicio. © JMA 2016. All rights reserved 204 58 Jerárquica de inyectores de dependencia • • • • Angular tiene un sistema de inyección de dependencia jerárquica. Hay un árbol de inyectores que se asemeja al árbol de componentes de una aplicación. Se pueden configurar los inyectores en cualquier nivel de ese árbol de componentes. De hecho, no existe el inyector. Una aplicación puede tener múltiples inyectores. Una aplicación angular es un árbol de componentes, cada instancia de componente tiene su propio inyector, que es paralelo al árbol de los inyectores. Cuando un componente solicita una dependencia, Angular intenta satisfácela con un proveedor registrado en el propio inyector de ese componente. Si el componente carece del proveedor, transfiere la solicitud al inyector de su componente anfitrión. Las solicitudes siguen burbujeando hasta que Angular encuentra un inyector que puede manejar la solicitud o llega al módulo. Si se queda sin antepasados y no está registrado en el módulo, Angular genera un error. La anotación @Host() impide el burbujeo y obliga a que el componente anfitrión tenga registrado el proveedor. constructor(@Host() public logger: Logger){} © JMA 2016. All rights reserved 205 Servicios importados • • Un módulo importado que añade proveedores a la aplicación puede ofrecer facilidades para la configuración de dichos proveedores. Por convención, el método estático forRoot de la clase módulo proporciona y configura al mismo tiempo los servicios. Recibe un objeto de configuración de servicio y devuelve un objeto ModuleWithProviders: static forRoot(config: MyServiceConfig): ModuleWithProviders { return { ngModule: CoreModule, providers: [{provide: MyServiceConfig, useValue: config }] }; } • En el servicio: constructor(@Optional() config: MyServiceConfig) { if (config) { … } } • En el módulo principal: imports: [ //… MyCoreModule.forRoot({…}), ], © JMA 2016. All rights reserved 206 59 COMPONENTES © JMA 2016. All rights reserved 207 Modelo de componentes • • • • • • Los componentes encapsulan el contenido (clase), la funcionalidad (clase), la presentación (plantilla) y la estética (css) de un elemento visual. Un componente puede estar compuesto por componentes que a su vez se compongan de otros componentes y así sucesivamente. Sigue un modelo de composición jerárquico con forma de árbol de componentes. La división sucesiva en componentes permite disminuir la complejidad funcional favoreciendo la reutilización y las pruebas. Los componentes establecen un cauce bien definido de entrada/salida para su comunicación con otros componentes. Los componentes son clases: – Decoradas con @Component – Que exponen datos (modelos) y funcionalidad (comandos) para su consumo por la plantilla – Opcionalmente, exponen propiedades (@Input) y eventos (@Output) para interactuar con otros componentes. © JMA 2016. All rights reserved 208 60 Árbol de componentes Aplicación Cabecera Menú Cuerpo Login Inicio Página 1 Tarjetas Tipo 1 Listado Consulta Página 2 Formulario Buscar Ábside Pie Nube Mapa Resultado Tipo 2 © JMA 2016. All rights reserved 209 Componente Clase Modelos Comandos Plantilla @Component HTML Metadatos Servicios Estilo CSS © JMA 2016. All rights reserved 210 61 @Component • selector: Selector CSS (Tag HTML) que indica a Angular que debe crear e instanciar el componente cuando se encuentra un elemento con ese nombre en el HTML. • template: Cadena con el contenido de la plantilla o • templateUrl: La url en la que se encuentra plantilla que se quiere vincular al componente. • styles: Cadena con el contenido del CSS o • styleUrls: Lista de urls a archivos de estilos que se aplican al componente (acepta Less, Sass, Stylus). • entryComponents: Lista de los Componentes/Directivas/Pipes que se insertan dinámicamente en la plantilla del el componente. • providers: Lista de los proveedores disponibles para este componente y sus hijos. © JMA 2016. All rights reserved 211 Componente import { Component } from '@angular/core'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { title: string = 'Hola Mundo'; constructor() { } despide(): void { this.title = 'Adios Mundo'; } } © JMA 2016. All rights reserved 213 62 Registrar • Globalmente: import { AppComponent } from './app.component'; @NgModule({ … declarations: [ AppComponent ], … }) export class AppModule { } • En el contenedor: import { HijoComponent } from './hijo.component'; @Component({ … entryComponents: [HijoComponent, …], … }) export class AppComponent { … } © JMA 2016. All rights reserved 214 Propiedades enlazables • • • Externamente se comportan como un atributo público. Internamente están compuesta por dos métodos, get/set que controlan como entra y sale la información. Las propiedades de solo lectura solo disponen del método get. No es obligatorio que tengan un reflejo directo en los atributos de la clase. class EmployeeVM { private _fullName: string; get fullName(): string { return this._fullName; } set fullName(newName: string) { if (this.validate(newName)) { this._fullName = newName; this.fullNameChanged(); } else { // … } } // … } let employee = new EmployeeVM(); employee.fullName = "Bob Smith"; © JMA 2016. All rights reserved 215 63 Atributos del selector • • Los atributos del selector del componente se comportan como los atributos de las etiquetas HTML, permitiendo personalizar y enlazar al componente desde las plantillas. Propiedades de entrada @Input() init: string; • Eventos de salida @Output() updated: EventEmitter = new EventEmitter(); this.updated.emit(value); • Propiedades bidireccionales: Es la combinación de una propiedad de entrada y un evento de salida con el mismo nombre (el evento obligatoriamente con el sufijo Change): @Input() size: number | string; @Output() sizeChange = new EventEmitter (); © JMA 2016. All rights reserved 216 Atributos del selector import { Component, EventEmitter, Input, Output } from '@angular/core'; @Component({ selector: 'my-sizer', template: ` ` }) export class SizerComponent { @Input() size: number | string; @Output() sizeChange = new EventEmitter(); dec() { this.resize(-1); } inc() { this.resize(+1); } resize(delta: number) { this.size = Math.min(40, Math.max(8, +this.size + delta)); this.sizeChange.emit(this.size); } } © JMA 2016. All rights reserved 217 64 Ciclo de vida • Cada componente tiene un ciclo de vida gestionado por el Angular. • Angular lo crea y pinta, crea y pinta sus hijos, comprueba cuando sus propiedades enlazadas a datos cambian, y lo destruye antes de quitarlo del DOM. • Angular ofrece ganchos al ciclo de vida que proporcionan visibilidad a dichos momentos clave y la capacidad de actuar cuando se producen. © JMA 2016. All rights reserved 218 Ciclo de vida Gancho Propósito y temporización ngOnChanges Responder cuando Angular (re) establece las propiedades de entrada enlazadas a datos. ngOnInit Inicializar el componente después de que Angular muestre las primeras propiedades enlazadas a datos y establece las propiedades de entrada del componente. ngDoCheck Llamado cada vez que las propiedades de entrada de un componente o una directiva se comprueban. Lo utilizan para extender la detección de cambios mediante la realización de una comprobación personalizada. ngAfterContentInit Responder después de que Angular proyecta el contenido externo en la vista del componente. ngAfterContentChecked Responder después de que Angular chequee el contenido proyectado en el componente. ngAfterViewInit Responder después de que Angular inicialice las vistas del componente y sus hijos. ngAfterViewChecked Responder después de que Angular chequee las vistas del componente y sus hijos. ngOnDestroy Limpiar justo antes de que Angular destruya el componente. © JMA 2016. All rights reserved 219 65 ESTILOS © JMA 2016. All rights reserved 220 Introducción • Las aplicaciones Angular utilizan CSS estándar para establecer la estética. Angular puede asociar el estilo al componente, lo que permite un diseño más modular que las hojas de estilo regulares. • Para cada componente Angular se puede definir no solo una plantilla HTML, sino también los estilos CSS que acompañan a esa plantilla, especificando los selectores, las reglas y las consultas de medios que se necesite. • Los estilos especificados en los metadatos se aplican solo dentro de la plantilla de ese componente, no son heredados por ningún componente anidado dentro de la plantilla ni por ningún contenido proyectado en el componente. © JMA 2016. All rights reserved 221 66 Modularidad de estilo • Se pueden usar los nombres y selectores de clases de CSS que tengan más sentido en el contexto de cada componente. • Los nombres de clase y los selectores son locales para el componente y no colisionan con las clases y los selectores utilizados en otras partes de la aplicación. • Los cambios en los estilos de otras partes de la aplicación no afectan los estilos del componente. • Se puede ubicar conjuntamente el código CSS de cada componente con el código de TypeScript y HTML del componente, lo que conduce a una estructura de proyecto prolija y ordenada. • Se puede cambiar o eliminar el código CSS del componente sin buscar en toda la aplicación para encontrar dónde se usa el código. © JMA 2016. All rights reserved 222 Selectores especiales • :host selector de pseudoclases para el elemento que aloja al componente. No se puede llegar al elemento host desde el interior del componente con otros selectores porque no forma parte de la propia plantilla del componente dado que está en la plantilla de un componente anfitrión. :host { border: 1px solid black; } :host(.active) { border-width: 3px; } • :host-context() selector que busca una clase CSS en cualquier antecesor del elemento host del componente, hasta la raíz del documento, solo es útil cuando se combina con otro selector para aplicar estilos basados en alguna condición externa al componente (si está contenido dentro de un elemento con determinada clase). :host-context(.theme-light) h2 { background-color: #eef; } © JMA 2016. All rights reserved 223 67 Agregar estilos a un componente • Estilos en los metadatos de los componentes • Archivos de estilo en los metadatos de los componentes • Etiqueta ` • Etiqueta en la plantilla (el enlace debe ser relativo a la raíz de la aplicación) template: ` ` • También puede importar archivos CSS en los archivos CSS usando la regla @import del CSS estándar (la URL es relativa al archivo CSS en el que está importando). © JMA 2016. All rights reserved 224 Encapsulación • • Los estilos CSS de los componentes se encapsulan en la vista del componente y no afectan el resto de la aplicación. Para controlar cómo ocurre esta encapsulación por componente se puede establecer el modo de encapsulación en los metadatos del componente: @Component({ styleUrls: ['./app.component.less'], encapsulation: ViewEncapsulation.Native }) • • • Native: la encapsulación de vista utiliza la implementación DOM nativa del sombreado del navegador (Shadow DOM) para adjuntar un DOM sombreado al elemento host del componente, y luego coloca la vista de componente dentro de esa sombra DOM. Los estilos del componente se incluyen dentro del DOM sombreado. (Requiere soporte nativo de los navegadores.) Emulated (por defecto): la encapsulación de vista emula el comportamiento del DOM sombreado mediante el preprocesamiento (y cambio de nombre) del código CSS para aplicar efectivamente el CSS a la vista del componente. None: no se encapsula la vista. Angular agrega el CSS a los estilos globales. Las reglas, aislamientos y protecciones no se aplican. Esto es esencialmente lo mismo que pegar los estilos del componente en el HTML. © JMA 2016. All rights reserved 225 68 Integración con preprocesadores CSS • Si se está utilizando AngularCLI, se pueden escribir archivos de estilo en Sass, Less o Stylus y especificar los archivos en @Component.styleUrls con las extensiones adecuadas (.scss, .less, .styl): @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.less'] }) ... • El proceso de compilación del CLI ejecutará el preprocesador de CSS pertinente. Esto no es posible con los estilos en línea. © JMA 2016. All rights reserved 226 Configuración • Se puede establecer como se generan por defecto los componentes: "schematics": { "@schematics/angular:component": { "inlineTemplate": true, "viewEncapsulation": "Emulated |Native | None" "styleext": "css | less | scss | styl " } }, … "options": { "styles": [ "src/styles.less" ], © JMA 2016. All rights reserved 227 69 PLANTILLAS © JMA 2016. All rights reserved 228 Plantillas • En Angular, las plantillas se escriben en HTML añadiéndole elementos y atributos específicos Angular. • Angular combina la plantilla con la información y funcionalidad de la clase del componente para crear la vista dinámica que el usuario visualiza en el navegador. • Casi toda las etiquetas del body HTML son válidas en las plantillas. La excepción principal es © JMA 2016. All rights reserved 361 JSONP (JSON con Padding) • Si no se importa el módulo HttpClientJsonpModule, las solicitudes de Jsonp llegarán al backend con el método JSONP, donde serán rechazadas. import { Injectable } from '@angular/core'; import { HttpClient } from '@angular/common/http'; @Injectable() export class WikipediaService { constructor(private http: HttpClient) {} search (term: string) { let wikiUrl = `http://en.wikipedia.org/w/api.php?search=${term}&action=opensearch&for mat=json`; return this.http.jsonp(wikiUrl, `callback`).subscribe( datos => this.items = datos, error => console.error(`Error: ${error}`) ); } } © JMA 2016. All rights reserved 362 122 Eventos • Los eventos trabajan en un nivel más bajo que las solicitudes. Una sola solicitud puede generar múltiples eventos. • Tipos de eventos: – Sent: La solicitud fue enviada. – ResponseHeader: Se recibieron el código de estado de respuesta y los encabezados. – UploadProgress: Se ha recibido un evento de progreso de subida. – DownloadProgress: Se ha recibido un evento de progreso de descarga. – Response: Se ha recibido la respuesta completa incluyendo el cuerpo. – User: Un evento personalizado de un interceptor o un backend. © JMA 2016. All rights reserved 363 Eventos de progreso • A veces las aplicaciones necesitan transferir grandes cantidades de datos, como por ejemplo subir ficheros, y esas transferencias pueden tomar mucho tiempo. • Es una buena práctica para la experiencia de usuario proporcionar información sobre el progreso de tales transferencias. this.http.post('/upload/file', file, { reportProgress: true, }) .subscribe(event => { if (event.type === HttpEventType.UploadProgress) { const percentDone = Math.round(100 * event.loaded / event.total); console.log(`File is ${percentDone}% uploaded.`); } else if (event instanceof HttpResponse) { console.log('File is completely uploaded!'); } }); © JMA 2016. All rights reserved 364 123 Interceptores • Una característica importante de HttpClient es la interceptación: la capacidad de declarar interceptores que se sitúan entre la aplicación y el backend. • Cuando la aplicación hace una petición, los interceptores la transforman antes de enviarla al servidor. • Los interceptores pueden transformar la respuesta en su camino de regreso antes de que la aplicación la vea. • Esto es útil para múltiples escenarios, desde la autenticación hasta el registro. • Cuando hay varios interceptores en una aplicación, Angular los aplica en el orden en que se registraron. © JMA 2016. All rights reserved 365 Crear un interceptor • Los interceptores son servicios que implementan el interfaz HttpInterceptor, que requiere el método intercept: intercept(req: HttpRequest , next: HttpHandler): Observable > { return next.handle(req); } • next siempre representa el siguiente interceptor en la cadena, si es que existe, o el backend final si no hay más interceptores. • La solicitud es inmutable para asegurar que los interceptores vean la misma petición para cada reintento. Para modificarla es necesario crear una nueva con el método clone(): return next.handle(req.clone({url: req.url.replace('http://', 'https://')})); • Se registran como un servicio múltiple sobre HTTP_INTERCEPTORS en el orden deseado: { provide: HTTP_INTERCEPTORS, useClass: MyInterceptor, multi: true, }, © JMA 2016. All rights reserved 366 124 Modificar la petición import { HttpEvent, HttpInterceptor, HttpHandler, HttpRequest } from '@angular/common/http'; @Injectable() export class AuthInterceptor implements HttpInterceptor { constructor(private auth: AuthService) { } intercept(req: HttpRequest , next: HttpHandler): Observable > { if (!req.withCredentials || ! this.auth.isAutenticated) { return next.handle(req); } const authReq = req.clone({ headers: req.headers.set('Authorization', this.auth.AuthorizationHeader) }); return next.handle(authReq); } } © JMA 2016. All rights reserved 367 Modificar la respuesta import { HttpEvent, HttpInterceptor, HttpHandler, HttpRequest, HttpResponse } from '@angular/common/http'; import { tap, finalize } from 'rxjs/operators'; @Injectable() export class LoggingInterceptor implements HttpInterceptor { intercept(req: HttpRequest , next: HttpHandler): Observable > { const started = Date.now(); let ok: string; return next.handle(req) .pipe( tap( event => ok = event instanceof HttpResponse ? 'succeeded' : '', error => ok = 'failed' ), finalize(() => { console.log(`${req.method} "${req.urlWithParams}" ${ok} in ${Date.now() - started} ms.`); }) ); } } © JMA 2016. All rights reserved 368 125 Protección ante XSRF • Cross-Site Request Forgery (XSRF) explota la confianza del servidor en la cookie de un usuario. HttpClient soporta el mecanismo “Cookie-to-Header Token” para prevenir ataques XSRF. – El servidor debe establecer un token en una cookie de sesión legible en JavaScript, llamada XSRF-TOKEN, en la carga de la página o en la primera solicitud GET. En las solicitudes posteriores, el cliente debe incluir el encabezado HTTP X-XSRF-TOKEN con el valor recibido en la cookie. – El servidor puede verificar que el valor en la cookie coincida con el del encabezado HTTP y, por lo tanto, asegúrese de que sólo el código que se ejecutó en su dominio pudo haber enviado la solicitud. – El token debe ser único para cada usuario y debe ser verificable por el servidor. Para mayor seguridad se puede incluir el token en un resumen de la cookie de autenticación de su sitio. • Para establecer nombres de cookies / encabezados personalizados: imports: [ // … HttpClientXsrfModule.withConfig({ cookieName: 'My-Xsrf-Cookie', headerName: 'My-Xsrf-Header', }),] • El servicio backend debe configurarse para establecer la cookie y verificar que el encabezado está presente en todas las solicitudes elegibles. © JMA 2016. All rights reserved 369 JWT: JSON Web Tokens https://jwt.io • JSON Web Token (JWT) es un estándar abierto (RFC-7519) basado en JSON para crear un token que sirva para enviar datos entre aplicaciones o servicios y garantizar que sean válidos y seguros. • El caso más común de uso de los JWT es para manejar la autenticación en aplicaciones móviles o web. Para esto cuando el usuario se quiere autenticar manda sus datos de inicio del sesión al servidor, este genera el JWT y se lo manda a la aplicación cliente, posteriormente en cada petición el cliente envía este token que el servidor usa para verificar que el usuario este correctamente autenticado y saber quien es. • Se puede usar con plataformas IDaaS (Identity-as-a-Service) como Auth0 que eliminan la complejidad de la autenticación y su gestión. • También es posible usarlo para transferir cualquier datos entre servicios de nuestra aplicación y asegurarnos de que sean siempre válido. Por ejemplo si tenemos un servicio de envío de email otro servicio podría enviar una petición con un JWT junto al contenido del mail o cualquier otro dato necesario y que estemos seguros que esos datos no fueron alterados de ninguna forma. © JMA 2016. All rights reserved 370 126 AuthService @Injectable({providedIn: 'root'}) export class AuthService { private isAuth = false; private authToken: string = ''; private name = ''; constructor() { if (localStorage && localStorage.AuthService) { const rslt = JSON.parse(localStorage.AuthService); this.isAuth = rslt.isAuth; this.authToken = rslt.authToken; this.name = rslt.name; } } get AuthorizationHeader() { return this.authToken; } get isAutenticated() { return this.isAuth; } get Name() { return this.name; } login(authToken: string, name: string ) { this.isAuth = true; this.authToken = authToken; this.name = name; if (localStorage) { localStorage.AuthService = JSON.stringify({isAuth, authToken, name}); } } logout() { this.isAuth = false; this.authToken = ''; this.name = ''; if (localStorage) { localStorage.removeItem('AuthService'); } } } © JMA 2016. All rights reserved 371 LoginService @Injectable({providedIn: 'root'}) export class LoginService { constructor(private http: HttpClient, private auth: AuthService) { } get isAutenticated() { return this.auth.isAutenticated; } get Name() { return this.auth.Name; } login(usr: string, pwd: string) { return new Observable(observable => this.http.post('http://localhost:4321/login', { name: usr, password: pwd }) .subscribe( data => { if(data['success']) { this.auth.login(data['token'], data['name']); } observable.next(this.auth.isAutenticated); }, (err: HttpErrorResponse) => { observable.error(err); } ) ); } logout() { this.auth.logout(); } } © JMA 2016. All rights reserved 372 127 ENRUTADO © JMA 2016. All rights reserved 375 Introducción • El enrutado permite tener una aplicación de una sola página, pero que es capaz de representar URL distintas, simulando lo que sería una navegación a través páginas web, pero sin salirnos nunca de la página inicial. Esto permite: – Memorizar rutas profundas dentro de nuestra aplicación. Podemos contar con enlaces que nos lleven a partes internas (deeplinks), de modo que no estemos obligados a entrar en la aplicación a través de la pantalla inicial. – Eso facilita también el uso natural del sistema de favoritos (o marcadores) del navegador, así como el historial. Es decir, gracias a las rutas internas, seremos capaces de guardar en favoritos un estado determinado de la aplicación. A través del uso del historial del navegador, para ir hacia delante y atrás en las páginas, podremos navegar entre pantallas de la aplicación con los botones del navegador. – Mantener y cargar módulos en archivos independientes, lo que reduce la carga inicial y permite la carga perezosa. © JMA 2016. All rights reserved 376 128 Rutas internas • • En las URL, la “almohadilla“, el carácter “#“, sirve para hacer rutas a anclas internas: zonas de una página. Cuando se pide al navegador que acceda a una ruta creada con “#“ éste no va a recargar la página (cargando un nuevo documento que pierde el contexto actual), lo que hará es buscar el ancla que corresponda y mover el scroll de la página a ese lugar. – http://example.com/index.html – http://example.com/index. html#/seccion – http://example.com/index. html#/pagina_interna • • • Es importante fijarse en el patrón "#/", sirve para hacer lo que se llaman "enlaces internos" dentro del mismo documento HTML. En el caso de Angular no habrá ningún movimiento de scroll, pues con Javascript se detectará el cambio de ruta en la barra de direcciones para intercambiar la vista que se está mostrando. Los navegadores HTML5 modernos admiten history.pushState, una técnica que cambia la ubicación y el historial de un navegador sin activar una solicitud de página del servidor. El enrutador puede componer una URL "natural" que es indistinguible de una que requeriría una carga de página. © JMA 2016. All rights reserved 377 Hash Bag • Dado que los robots indexadores de contenido de los buscadores no siguen los enlaces al interior de la pagina (que asumen como ya escaneada), el uso del enrutado con # que carga dinámicamente el contenido impide el referenciado en los buscadores. • Para indicarle al robot que debe solicitar el enlace interno se añade una ! después de la # quedando la URL: http://www.example.com/index.html#!ruta © JMA 2016. All rights reserved 378 129 Angular Router • • • El Angular Router ( "router") toma prestado el modelo deeplinks. Puede interpretar una URL del navegador como una instrucción para navegar a una vista generada por el cliente y pasar parámetros opcionales en la ruta al componente para decidir qué contenido específico se quiere manejar. El Angular router es un servicio opcional que presenta la vista de un componente en particular asociado a una determinada URL. No es parte del núcleo Angular. Es un paquete de la biblioteca, @angular/router, a importar en el módulo principal como se haría con cualquier otro modulo Angular. import { RouterModule, Routes } from '@angular/router'; • • La aplicación tendrá un único router. Cuando la URL del navegador cambia, el router busca una correspondencia en la tabla de rutas para determinar el componente que debe mostrar. Las aplicaciones de enrutamiento deben agregar un elemento index.html al principio de la etiqueta para indicar al enrutador cómo componer las URL de navegación. © JMA 2016. All rights reserved 379 Tabla de rutas • • La tabla de ruta es un conjunto de objetos Route. Toda ruta tiene una propiedad path con la ruta que se utiliza como patrón de coincidencia. Puede ser: – – – – • • Única: path: 'mi/ruta/particular' Parametrizada: path: 'mi/ruta/:id' Vacía (solo una vez): path: '' Todas las demás (solo una vez): path: '**' Dado que la búsqueda se realiza secuencialmente la tabla debe estar ordenada de rutas mas especificas a las mas generales. La ruta puede estar asociada a: – Un componente: component: MyComponent – Otra ruta (redirección): redirectTo: '/otra/ruta' – Otro módulo (carga perezosa): loadChildren: 'ruta/otro/modulo' • Adicionalmente se puede indicar: – – – – – outlet: Destino de la ruta. pathMatch: prefix | full children: Subrutas data: datos adicionales Servicios canActivate, canActivateChild, canDeactivate, canLoad © JMA 2016. All rights reserved 380 130 Registrar enrutamiento const routes: Routes = [ { path: '', component: HomeComponent, pathMatch: 'full' }, { path: 'path/:routeParam', component: MyComponent1 }, { path: 'staticPath', component: MyComponent2 }, { path: 'oldPath', redirectTo: '/newPath' }, { path: 'path', component: MyComponent3 , data: { message: 'Custom' } }, { path: '**', component: ErrorComponent }, ]; @NgModule({ imports: [ BrowserModule, RouterModule.forRoot(routes) ], // … }) export class AppModule { } © JMA 2016. All rights reserved 381 Directivas • Punto de entrada por defecto: • Punto de entrada con nombre, propiedad outlet de la ruta: • Generador de referencias href: • Nombre de la Class CSS asociada a ruta actual: © JMA 2016. All rights reserved 382 131 Trabajar con rutas • Importar clases: import { Router, ActivatedRoute } from '@angular/router'; • Inyectar dependencias: constructor(private route: ActivatedRoute, private router: Router) { } • Decodificar parámetros y ruta: – Valor actual (Instantánea): let id = this.route.snapshot.params['id']; – Detección de cambios (observable) route.url.map(segments => segments.join('')); let sid = this.route.queryParamMap.pipe(map(p => p.get('sid') || 'None')); this.token = this.route.fragment.pipe(map(f => f || 'None')); • Navegación desde el código: this.router.navigate(['/ruta/nueva/1']); © JMA 2016. All rights reserved 383 Decodifica ruta ngOnInit() { let id = this.route.snapshot.params['id']; if (id) { if (this.route.snapshot.url.slice(-1)[0].path === 'edit') { this.vm.edit(+id); } else { this.vm.view(+id); } } else if (this.route.snapshot.url.slice(-1)[0].path === 'add') { this.vm.add(); } else { this.vm.load(); } } © JMA 2016. All rights reserved 384 132 Parámetros observables private obs$: any; ngOnInit() { this.obs$ = this.route.paramMap.subscribe( (params: ParamMap) => { const id = +params.get('id'); // (+) converts string 'id' to a number if (id) { this.vm.edit(id); } else { this.router.navigate(['/404.html']); } }); } ngOnDestroy() { this.obs$.unsubscribe(); } © JMA 2016. All rights reserved 385 Eventos de ruta Evento Desencadenado NavigationStart cuando comienza la navegación. RoutesRecognized cuando el enrutador analiza la URL y las rutas son reconocidas. RouteConfigLoadStart antes de que empiece la carga perezosa. RouteConfigLoadEnd después de que una ruta se haya cargado de forma perezosa. NavigationEnd cuando la navegación termina exitosamente. NavigationCancel cuando se cancela la navegación: un guardián devuelve falso. NavigationError cuando la navegación falla debido a un error inesperado. • Durante cada navegación, el Router emite eventos de navegación a través de la propiedad observable Router.events a la se le puede agregar suscriptores para tomar decisiones basadas en la secuencia de eventos. this.router.events.subscribe(ev => { if(ev instanceof NavigationEnd) { this.inicio = (ev as NavigationEnd).url == '/'; } }); © JMA 2016. All rights reserved 386 133 Guardianes de rutas • Los guardianes controlan el acceso a las rutas por parte del usuario o si se le permite abandonarla: – CanActivate: verifica el acceso a la ruta. – CanActivateChild: verifica el acceso a las ruta hijas. – CanDeactivate: verifica el abandono de la ruta, permitiendo descartar acciones pendientes que se perderán. – CanLoad: verifica el acceso a un módulo que requiere carga perezosa. • Para crear un guardián hay que crear un servicio que implemente el correspondiente interfaz y registrarlo en cada ruta a controlar. @Injectable() export class AuthGuard implements CanActivate { constructor(private authService: AuthService, private router: Router) {} canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean { return this.authService.isAutenticated; } } { path: 'admin', component: AdminComponent, canActivate: [AuthGuard], }, © JMA 2016. All rights reserved 387 Obtener datos antes de navegar • • En algunos casos es interesante resolver el acceso a datos antes de navegar para poder redirigir en caso de no estar disponibles. Servicio: @Injectable({ providedIn: 'root', } ) export class DatosResolve implements Resolve { constructor(private dao: DatosDAOService, private router: Router) {} resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable { return this.dao.get(+route.paramMap.get('id')).pipe( take(1), map(data => { if (data) { return data; } else { // id not found this.router.navigate(['/404.html']); return null; } }), catchError(err => { this.router.navigate(['/404.html']); return empty(); }) ); } } © JMA 2016. All rights reserved 388 134 Obtener datos antes de navegar • En la tabla de rutas: { path: 'datos/:id', component: DatosViewComponent, resolve: {elemento: DatosResolve} }, • En el componente: ngOnInit() { this.route.data.subscribe((data: { elemento: any }) => { let e = data.elemento; // … }); © JMA 2016. All rights reserved 389 Mantenimiento de estado • Uno de los posibles aspectos problemáticos del enrutado es que los componentes se instancian con cada vista donde se estén usando, cada vez que se carga la ruta. • Por este motivo todos los datos que se inicializan y se vuelven a poner a sus valores predeterminados cuando carga cualquier la vista. • El mantenimiento de estado consiste en guardar los datos desde que el componente se destruye hasta que se vuelve a crear y se restaura el estado, situación antes de destruirse. • A través de los servicios se puede implementar el mantenimiento de estado de los componentes en caso de ser necesario. – El patrón singleton, utilizado en la inyección de dependencias, asegura que sólo existe una instancia de ellos en el modulo, por lo que no pierden su estado, y, si hay varios componentes que dependen de un mismo servicio, todos recibirán la misma instancia del objeto. © JMA 2016. All rights reserved 390 135 Patrón Composite View © JMA 2016. All rights reserved 391 outlet • Punto de entrada con nombre, propiedad outlet de la ruta: • En la tabla de rutas: { path: 'mypath', component: MyComponent, outlet: 'aside' } • Generador de referencias secundarias: ... • Ruta múltiple: http://example.com/mainpath(aside:mypath) • Navegación desde el código: this.router.navigate([{ outlets: { aside: ['mypath'] } }]); • Eliminar el contenido: this.router.navigate([{ outlets: { aside: null } }]); © JMA 2016. All rights reserved 392 136 Lazy loading • La carga diferida de módulos (lazy loading) se controla con el router: export const routes: Routes = [ // … { path: 'admin', loadChildren: './admin/admin.module#AdminModule' }, ]; • El localizador loadChildren de carga perezosa es una cadena, no un tipo. • La cadena identifica tanto el módulo de archivo (módulo TypeScript) como el módulo de clase (módulo Angular), este último separado del anterior por una #. ./admin/admin.module#AdminModule equivale a una importación en app.module import { AdminModule } from './admin/admin.module'; © JMA 2016. All rights reserved 393 Lazy loading • El módulo LazyLoad no debe estar entre los imports del @NgModule del AppModule. • WebPack crea un bundle por cada módulo enrutado como loadChildren identificado por un número y la sub extensión .chunk – 0.chunk.js, 1.chunk.js, 2.chunk.js, … • El módulo LazyLoad debe tener una tabla de rutas con la ruta vacía que indica el componente inicial del módulo. export const routes: Routes = [ { path: '', component: AdminMainComponent }, { path: 'users', component: UsersComponent }, { path: 'roles', component: RolesComponent }, ]; • La tabla de rutas, en el módulo LazyLoad se debe importar a través del forChild: @NgModule({ imports: [ RouterModule.forChild(routes), // … © JMA 2016. All rights reserved 394 137 DESPLIEGUE © JMA 2016. All rights reserved 395 Pruebas • Son imprescindibles en entornos de calidad: permite ejecutar las pruebas unitarias, las pruebas de extremo a extremo o comprobar la sintaxis. • Para comprobar la sintaxis: Hay que ejecutar el analizador con el comando: – ng lint • Para ejecutar tests unitarios: Se puede lanzar los tests unitarios con karma con el comando: – ng test • Para ejecutar tests e2e: Se puede lanzar los tests end to end con protractor con el comando: – ng e2e © JMA 2016. All rights reserved 396 138 Polyfill • • • Angular se basa en los últimos estándares de la plataforma web. Dirigirse a una gama tan amplia de navegadores es un reto porque no todos son compatibles con todas las funciones de los navegadores modernos. Un Polyfill puede ser un segmento de código o un plugin que permite tener las nuevas funcionalidades u objetos de HTML5 y ES2015 en aquellos navegadores que nativamente no lo soportan. Es necesario activar (des-comentar) en el fichero polyfills.ts las funcionalidades utilizadas. /** IE9, IE10 and IE11 requires all of the following polyfills. **/ import 'core-js/es6/symbol'; import 'core-js/es6/object'; // … import 'core-js/es6/set'; // … • Este archivo incorpora los polyfill obligatorios y muchos opcionales. Algunos polyfill opcionales se tendrá que instalar con npm. © JMA 2016. All rights reserved 397 Compilación • • Una aplicación Angular consiste principalmente en componentes y sus plantillas HTML. Debido a que los componentes y las plantillas proporcionadas por Angular no pueden ser entendidas directamente por el navegador, las aplicaciones de Angular requieren un proceso de compilación antes de que puedan ejecutarse en el navegador. Angular ofrece dos formas de compilar la aplicación: – – • Just-in-Time (JIT), que compila la aplicación en el navegador en tiempo de ejecución (la predeterminada cuando ejecuta los comandos de CLI ng build o ng serve). Ahead-of-Time (AOT), que compila la aplicación antes de que la descargue el navegador. El compilador Ahead-of-Time (AOT) convierte el código TypeScript y el HTML de la aplicación Angular en un eficiente código JavaScript, durante la fase de despliegue antes de que el navegador descargue y ejecute la aplicación. Las ventajas de la compilación AOT son: – – – – – Representación más rápida: Con AOT, el navegador descarga una versión precompilada de la aplicación. El navegador carga directamente el código ejecutable para que pueda procesar la aplicación de inmediato, sin esperar a compilarla primero. Menos peticiones asíncronas: El compilador incluye las plantillas HTML externas y las hojas de estilo CSS dentro de la aplicación JavaScript, eliminando solicitudes ajax separadas para esos archivos de origen. Tamaño de descarga del framework de Angular más pequeño: No es necesario descargar el compilador Angular si la aplicación ya está compilada. El compilador ocupa aproximadamente la mitad de Angular, por lo que omitirlo reduce drásticamente la carga útil de la aplicación. Detectar antes errores de plantillas: El compilador AOT detecta e informa de los errores de enlace de la plantilla durante el proceso de compilación antes de que los usuarios puedan verlos. Mejor seguridad: AOT compila plantillas y componentes HTML en archivos JavaScript mucho antes de que se sirvan al cliente. Sin plantillas para leer y sin el riesgo de evaluación de HTML o JavaScript del lado del cliente, hay menos oportunidades para ataques de inyección. © JMA 2016. All rights reserved 398 139 Despliegue • El despliegue más simple posible 1. 2. 3. • Generar la construcción de producción. Copiar todo dentro de la carpeta de salida (/dist por defecto) a una carpeta en el servidor. Configurar el servidor para redirigir las solicitudes de archivos faltantes a index.html. Construye la aplicación en la carpeta /dist – ng build – ng build --dev • Paso a producción, construye optimizándolo todo para producción – ng build --prod – ng build --prod --env=prod – ng build --target=production --environment=prod • Precompila la aplicación • Cualquier servidor es candidato para desplegar una aplicación Angular. No se necesita un motor del lado del servidor para componer dinámicamente páginas de aplicaciones porque Angular lo hace en el lado del cliente. La aplicaciones Angular Universal y algunas funcionalidades especiales requieren una configuración especial del servidor. – ng build --prod –aot • © JMA 2016. All rights reserved 399 https://angular.io/resources UTILIDADES © JMA 2016. All rights reserved 400 140 Módulos de terceros • Data Libraries – – – – • Angular Fire: The official library for Firebase and Angular Apollo: Apollo is a data stack for modern apps, built with GraphQL. Meteor: Use Angular and Meteor to build full-stack JavaScript apps for Mobile and Desktop. ngrx: Reactive Extensions for angular2 UI Components – – – – – – – – – – – – ag-Grid: A datagrid for Angular with enterprise style features such as sorting, filtering, custom rendering, editing, grouping, aggregation and pivoting. Angular Material 2: Material Design components for Angular Clarity Design System: UX guidelines, HTML/CSS framework, and Angular components working together to craft exceptional experiences Kendo UI: One of the first major UI frameworks to support Angular ng-bootstrap: The Angular version of the Angular UI Bootstrap library. This library is being built from scratch in Typescript using the Bootstrap 4 CSS framework. ng-lightning: Native Angular components & directives for Lightning Design System ng2-bootstrap: Native Angular2 directives for Bootstrap Onsen UI: UI components for hybrid mobile apps with bindings for both Angular 1 & 2. Prime Faces: PrimeNG is a collection of rich UI components for Angular Semantic UI: UI components for Angular using Semantic UI Vaadin: Material design inspired UI components for building great web apps. For mobile and desktop. Wijmo: High-performance UI controls with the most complete Angular support available. © JMA 2016. All rights reserved 401 141
Source Exif Data:
File Type : PDF File Type Extension : pdf MIME Type : application/pdf PDF Version : 1.7 Linearized : No Page Count : 141 Language : es-ES Tagged PDF : Yes XMP Toolkit : 3.1-701 Producer : Microsoft® PowerPoint® 2019 Title : Manual de Angular Creator : Javier Creator Tool : Microsoft® PowerPoint® 2019 Create Date : 2019:02:18 08:06:24+01:00 Modify Date : 2019:02:18 08:06:24+01:00 Document ID : uuid:E004E729-41C8-455E-B26D-8BD37D5CAAB6 Instance ID : uuid:E004E729-41C8-455E-B26D-8BD37D5CAAB6 Author : JavierEXIF Metadata provided by EXIF.tools