Escuela*Técnica*Superior*de*Ingeniería*de*Sistemas...
Transcript of Escuela*Técnica*Superior*de*Ingeniería*de*Sistemas...
!
!
!
UNIVERSIDAD*POLITÉCNICA*DE*MADRID*Escuela*Técnica*Superior*de*Ingeniería*de*Sistemas*Informáticos*
!!
MÁSTER!EN!INGENIERÍA!WEB!!!Proyecto!Fin!de!Máster!!
!
Comparativa!entre!Angular!y!AngularJS.!!
Evolución!a!Angular!5.!!!
!!
!
Autor!Angela*Serrano*Sánchez*
!!
Tutor*Santiago*Alonso*Villaverde*
****
29*de*junio*de*2018
! Comparativa*entre*Angular*y*AngularJS.*Evolución*a*Angular*5.!
! !
AGRADECIMIENTOS
Gracias!a!mi!tutor,!Santiago!Alonso!Villaverde,!por!su!infinita!paciencia!tutorizando!
este!trabajo.!!
Gracias! también! a!mis! padres! por! enseñarme! que! la! constancia,! el! trabajo! y! la!
fuerza!de!voluntad!te!ayudan!a!conseguir!todos!tus!objetivos.!
! *
! Comparativa*entre*Angular*y*AngularJS.*Evolución*a*Angular*5.!
! !
RESUMEN
Este!trabajo!se!centra!en!el!estudio!teórico!y!práctico!de!Angular!en!su!versión!más!
actual!(v.!6)!y!en!su!posterior!comparativa!con!su!predecesor!AngularJS,!también!en!su!
versión!más!actual!(v.!1.7)!
Tras!un!breve!repaso!por!el!origen!de!los!lenguajes!de!programación!en!el!lado!del!
cliente!y!después!de!ver! la!evolución!sufrida!en!Angular,!desde!la!primera!versión!de!
AngularJS!hasta!el!día!de!hoy,!se!da!paso!a!una!descripción!detallada!de!la!arquitectura!
de!Angular!6!y!de!todos!sus!elementos!y!componentes.!
Se!desarrolla!así!mismo!una!pequeña!aplicación!bajo!este!framework!para!asentar!los!conocimientos!teóricos!y!que!sirva!a!su!vez!para!realizar!una!comparativa!práctica!
con!AngularJS.!
Tras!la!comparativa!se!realiza!una!evaluación!de!las!ventajas!que!aporta!Angular!
sobre!AngularJS.!
Por!último,!y!tras!todo!lo!anterior!se!valoran!el!futuro!y!la!continidad!de!Angular!
como!conclusión!final!de!este!informe.!
1.1.! PALABRAS CLAVE
Angular,!AngularJS,!framework,!arquitectura,!comparativa,!ventajas!
!
! Comparativa*entre*Angular*y*AngularJS.*Evolución*a*Angular*5.!
! !
ABSTRACT
This!work! focuses! on! the! theoretical! and! practical! study! of! Angular! in! its!most!
current!version!(v.!6)!and!its!subsequent!comparison!with!its!predecessor!AngularJS,!also!
in!its!most!current!version!(v.!1.7)!
After!a!brief!review!of!the!origin!of!the!programming!languages!on!the!client!side!
and!after!seeing!the!evolution!of!Angular,!from!the!first!verision!of!AngularJS!until!today,!
a! detailed! description! of! the! architecture! of! Angular! 6! and! all! its! elements! and!
components.!
It!also!develops!a!small!application!under!this!framework!to!settle!the!theoretical!
knowledge!and!serves!in!turn!to!make!a!practical!comparison!with!AngularJS.!
After!the!comparison,!an!evaluation!of!the!advantages!that!Angular!provides!on!
AngularJS!is!made.!
Finally,!and!after!all!the!above,!the!future!and!the!continuity!of!Angular!are!valued!
as!the!final!conclusion!of!this!report.!
1.2.! KEYWORDS
Angular,!AngularJS,!framework,!arquitecture,!comparative,!advantages!
! Comparativa*entre*Angular*y*AngularJS.*Evolución*a*Angular*5.!
! !
TABLA DE CONTENIDOS
Objetivos* 15!
1.! Introducción* 17!1.1.! Evolución*y*desarrollo*de*los*lenguajes*frontFend* 17!1.2.! Introducción*a*Angular.*Evolución*del*framework.* 20!
2.! Angular* 23!2.1.! Arquitectura* 23!2.2.! NgModules*y*Bootstrapping* 26!
2.2.1.! Bootstrapping! 26!2.2.2.! El!decorador!@NgModule! 26!
2.2.2.1.! El!array!declarations! 27!2.2.2.2.! El!array!imports! 27!2.2.2.3.! El!array!providers! 27!2.2.2.4.! El!array!bootstrap! 28!
2.2.3.! Módulos!Característicos! 28!2.2.4.! NgModules!de!Angular! 29!
2.3.! Componentes* 29!2.3.1.! Metadatos,!decoradores!y!el!decorador!@Component! 30!2.3.2.! Plantillas!y!Data!Binding! 31!
2.3.2.1.! Expresiones! 32!2.3.2.2.! Instrucciones! 33!2.3.2.3.! Data!Binding! 33!
2.3.3.! Comunicación!entre!componentes! 37!2.3.4.! Ciclo!de!vida!del!componente!(Lifecycle*hook)! 38!
2.3.4.1.! ngOnChange! 39!2.3.4.2.! ngOnInit! 39!2.3.4.3.! ngDoCheck! 40!2.3.4.4.! ngOnDestroy! 40!2.3.4.5.! ngAfterContent!y!ngAfterView! 40!
2.4.! Directivas* 41!2.4.1.! Directivas!estructurales! 41!
2.4.1.1.! Directivas!estructurales!predefinidas! 42!2.4.1.2.! Directivas!estructurales!personalizadas! 44!
2.4.2.! Directivas!de!atributos! 44!2.4.2.1.! Directivas!de!atributos!predefinidas! 44!2.4.2.2.! Directivas!de!atributos!personalizadas! 46!
2.5.! Filtros* 46!2.5.1.! Filtros!predefinidos! 47!2.5.2.! Filtros!personalizados! 47!2.5.3.! Filtros!puros!e!impuros! 47!
2.6.! Servicios*e*Inyección*de*dependencias* 48!2.6.1.! Inyección!de!dependencias!en!Angular! 48!
2.6.1.1.! Inyectores! 49!2.6.1.2.! Proveedores! 50!2.6.1.3.! Inyección!de!servicios! 52!
! [UPM]!Máster*en*Ingeniería*Web!2.6.2.! Jerarquía!de!Inyectores! 52!2.6.3.! Servicios!de!Angular! 53!
2.7.! RxJS*y*Angular* 53!2.7.1.! Reactive!Programming! 53!2.7.2.! Observables!&!RxJS! 54!2.7.3.! Observables!en!Angular!con!RxJS! 55!
2.7.3.1.! EventEmitter! 55!2.7.3.2.! http! 55!2.7.3.3.! Async!Pipe! 55!2.7.3.4.! Routing! 55!2.7.3.5.! Reactive!Forms! 56!
2.8.! Formularios* 56!2.8.1.! Formularios!basados!en!plantillas! 57!
2.8.1.1.! Validaciones!de!formularios!basados!en!plantillas! 58!2.8.2.! Formularios!reactivos! 58!
2.8.2.1.! FormControls!y!FormGroups! 59!2.8.2.2.! FormBuilder! 60!2.8.2.3.! Validaciones!de!formularios!reactivos! 60!
2.9.! Navegación*y*Routing* 61!2.9.1.! Configuración! 63!2.9.2.! Directivas! 66!
2.9.2.1.! Router!Outlet! 66!2.9.2.2.! Router!Link! 66!2.9.2.3.! RouterLinkActive! 67!
2.9.3.! Activated!Routes! 67!2.9.4.! Guardas!y!resolvers! 68!
2.10.! Conexión*con*el*servidor*y*HttpClient* 69!2.10.1.! Comunicación!con!el!servidor! 70!
2.10.1.1.! Petición!GET! 70!2.10.1.2.! Petición!POST! 71!2.10.1.3.! Petición!PUT! 72!2.10.1.4.! Petición!DELETE! 72!2.10.1.5.! Añadir!cabeceras! 72!
2.10.2.! Tratamiento!de!los!errores! 73!2.10.3.! Interceptar!peticiones!y!respuestas! 73!
3.! Angular*vs*AngularJS* 75!3.1.! La*aplicación.*SpotifyAngular.* 75!3.2.! Instalación* 79!
3.2.1.! Angular!CLI! 79!3.2.2.! Arquitectura! 81!
3.2.2.1.! Arquitectura!de!AngularJS! 82!3.2.2.2.! Estructura!!de!un!proyecto!Angular!vs!AngularJS! 82!
3.2.3.! Módulos! 87!3.2.4.! Componentes! 90!
3.2.4.1.! Ciclos!de!vida!del!componente! 91!3.2.4.2.! Plantillas!y!Data!Binding! 92!
3.2.5.! Directivas! 95!3.2.6.! Filtros!vs!Pipes! 98!3.2.7.! Servicios!e!Inyección!de!Dependencias! 100!3.2.8.! Observables!vs!Promesas! 104!
! Comparativa*entre*Angular*y*AngularJS.*Evolución*a*Angular*5.!
! !
3.2.9.! Formularios! 105!3.2.10.! Navegación!y!Routing! 107!3.2.11.! Conexión!con!el!servidor! 111!
4.! Conclusiones.*Ventajas*y*futuro*de*Angula* 113!4.1.! Ventajas* 113!
4.1.1.! Puesta!en!Marcha! 113!4.1.2.! Modularidad! 113!4.1.3.! Arquitectura!basade!en!componentes! 113!4.1.4.! Inyección!de!dependencias! 114!4.1.5.! Rendimiento! 114!4.1.6.! Orientado!a!móviles! 115!4.1.7.! Librerías!de!Terceros! 115!4.1.8.! TypeScript!vs!JavaScript! 116!4.1.9.! Curva!de!aprendizaje! 116!
4.2.! Futuro*de*Angular* 117!
Bibliografía* 119!
!
! Comparativa*entre*Angular*y*AngularJS.*Evolución*a*Angular*5.!
! !
TABLA DE IMÁGENES
Imagen*1.*Comunicación*en*la*arquitectura*cliente/servidor* 18!Imagen*2.*Patrón*MVC*(Model[View[Controller* 19!Imagen*3.*Versionado*de*Angular* 21!Imagen*4.*Principios*de*la*arquitectura*basada*en*componentes* 24!Imagen*5.*Beneficios*de*la*arquitectura*basada*en*componentes* 25!Imagen*6.*Estructura*de*un*componente*en*Angular* 30!Imagen*7.*Tipos*de*Data*Binding* 34!Imagen*8.*Two[way*data*binding* 37!Imagen*9.*Métodos*del*ciclo*de*vida*de*un*componente*Angular* 39!Imagen*10.*Esquema*de*inyección*de*dependencias*en*Angular* 49!Imagen*11.*Enrutamiento*en*el*lado*del*servidor* 62!Imagen*12.*Enrutamiento*en*el*lado*del*cliente* 62!Imagen*13.*Diagrama*de*casos*de*uso*de*SpotifyAngular* 76!Imagen*14.*Pantalla*de*Log*In*de*SpotifyAngular* 77!Imagen*15.*Página*de*inicio*de*SpotifyAngular* 77!Imagen*16.*Página*de*perfil*del*usuario* 78!Imagen*17.*Página*con*vista*de*playlist*y*pop[up*de*creación*de*playlist* 78!Imagen*18.*Página*con*resultados*de*la*búsqueda* 79!Imagen*19.*Comandos*de*Angular*CLI* 80!Imagen*20.*Creación*de*elementos*con*Angular*CLI* 81!Imagen*21.*Estructura*de*un*proyecto*Angular* 83!Imagen*22.*Fichero*de*configuración*angular.json* 84!Imagen*23.*Puesta*en*marcha*de*un*proyecto*Angular* 84!Imagen*24.*Organización*del*proyecto*SpotifyAngular* 85!Imagen*25.*Estructura*de*un*proyecto*AngularJS* 86!Imagen*26.Vista*del*componente*albums.component.ts* 93!Imagen*27.*El*usuario*sigue*al*artista* 98!Imagen*28.*Visualización*del*nombre*del*artista*sin*filtro* 100!Imagen*29.*Visualización*del*nombre*del*artista*con*filtro* 100!Imagen*30.*Playlists*recuperadas*de*la*petición*al*servidor* 104!Imagen*31.*Ruta*de*navegación*con*el*identificador*del*artista* 110!Imagen*32.*Angular*en*el*desarrollo*de*aplicaciones*móviles* 115!Imagen*33.*Formulario*en*PopUp*creado*con*el*elemento*'Dialog'*de*Angular*Materials* 116!
!
! Comparativa*entre*Angular*y*AngularJS.*Evolución*a*Angular*5.!
Angela!Serrano!Sánchez!! ! Página!15!!
OBJETIVOS
El! siguiente! documento! tiene! como!objetivo! realizar! una! comparativa! completa!
entre!la!primera!y!última!versión!de!Angular,!uno!de!los!frameworks!frontFend!para!el!desarrollo! de! aplicaciones! web!más! utilizados! y! extendidos! actualmente! en! todo! el!
mundo.!
Mediante!un!breve! repaso!por! la!evolución!del!desarrollo!web,! se!pretende!dar!
explicación!a!la!necesidad!de!aplicar!buenas!prácticas!en!el!código!desarrollado!en!el!
lado!del!cliente!y!entender!así!porqué!surgen!los!frameworks,!que!dan!estructura!a!estos!lenguajes!de!programación!(principalmente!JavaScript).!
Una!vez!conseguido!el!objetivo!anterior,!se!pretende!estudiar!en!profundidad! la!
arquitectura!y!elementos!de!Angular,!y!a!partir!de!ahí!conocer!las!principales!similitudes!
y!diferencias!de!ambas!versiones!analizando!las!posibles!ventajas!que!aportan!cada!una!
Angular!sobre!AngularJS!en!el!desarrollo!web,!en!términos!de!facilidad!de!uso,!curva!de!
aprendizaje,!rendimiento,!etc.!
Para!ello,!se!llevará!a!cabo!el!desarrollo!una!pequeña!aplicación!web!en!Angular,!
que!servirá!para!poder!aplicar!una!comparativa!práctica,!que!ayude!a!su!vez!a!afianzar!
las!bases!teóricas!de!cada!arquitectura.!
!
! Comparativa*entre*Angular*y*AngularJS.*Evolución*a*Angular*5.!
Angela!Serrano!Sánchez!! ! Página!17!!
1.! INTRODUCCIÓN
Para! llegar! a! comprender! porqué! surgen! los! framework! para! el! desarrollo! con!lenguajes!de!frontFend,!es!necesario!analizar!la!evolución!de!estas!tecnologías!desde!el!nacimiento!de!la!web,!hasta!el!día!de!hoy.!!
1.1.! EVOLUCIÓN Y DESARROLLO DE LOS LENGUAJES FRONT-END
Internet!nace!como!el!primer!conjunto!descentralizado!de!redes!de!comunicación!
interconectadas,!para!dar!soporte!a!la!compartición!de!información!y!recursos!entre!los!
nodos!que!forman!parte!de!dicha!red.!Sus!orígenes!se!remontan!a!la!década!de!1960,!
bajo!el!proyecto!denominado!ARPANet!(Advanced*Research*Projects*Agency*Network),!se!trata!de!la!primera!red!de!interconexión!creada!por!encargo!del!Departamento!de!
Defensa!de!los!Estados!Unidos!para!ser!utilizada!como!medio!de!comunicación!entre!las!
diferentes!instituciones!académicas!y!estatales.!
A!medida!que!crece!la!red!en!número!de!nodos!y!aumenta!el!nivel!de!datos!que!
ésta!maneja,!se!hace!necesario!mejorar!el!acceso!a!la!información!compartida!y!la!forma!
en! que! ésta! es! presentada,! ya! que! los! ordenadores! y! los! sistemas! operativos! que!
componían! la! red!eran!diferentes.!El!primero!en!considerar!estos!problemas! fue!Tim*BernersFLee!que!escribió!una!propuesta!en!1989!para!crear!“una!gran!base!de!datos!de!hipertexto!con!enlaces!tipados”.!Comenzó!a!implementar!su!sistema!sobre!la!estación!
de! trabajo! NeXT1,! de! este! modo! hacia! finales! del! año! 1990,! BernersFLee! había!desarrollado!todas!las!herramientas!necesarias!para!trabajar!en!la!Web:!el!Protocolo!de!
transferencia!de!hipertexto!(HTTP!por!sus!siglas!en!inglés),!el!Lenguaje!de!Marcado!de!
Hipertexto!(HTML!por!sus!siglas!en!inglés),!el!primer!navegador!web!WorldWideWeb,!que! fue! también!un! editor! de! páginas!web,! el! primer! servidor! de! aplicaciones!HTTP!
(luego!conocido!como!CERN!httpd),!el!primer!servidor!web!y!las!primeras!páginas!web!
que!describían!el!proyecto!mismo.!!
La!!World*Wide*Web!se!convierte!así!en!el!primer!cliente!web!y!HTML!en!el!primer!
lenguaje! de! frontFend,! que! maqueta! la! información! para! que! se! visualice! de! forma!
homogénea!en!todos!los!navegadores!web.!
Poco! después! surge! como! estándar! CSS! (Cascade* Style* Sheets),! hojas! de! estilo!específicas!para!HTML.!El!organismo!W3C!(World*Wide*Web*Consortium)2!propuso! la!
creación!de!un! lenguaje!de!hojas!de!estilos!específico!para!HTML.!De!entre!todas! las!
propuestas!realizadas,!!las!dos!que!se!tuvieron!en!cuenta!fueron!CHSS!(Cascading*HTML*
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!1!Computadora!creada!por!Steve!Jobs!y!fabricada!por!la!compañía!NEXT,!que!utilizó!Tim!BernersoLee!para!desarrollar!la!WorldWideWeb.!2!Organismo!encargado!de!crear!todos!los!estándares!relacionados!con!la!web.! !
! [UPM]!Máster*en*Ingeniería*Web!
Página!18!
Style*Sheets)!propuesta!por!Håkon*Wium*Lie!y!SSP!(StreamFbased*Style*Sheet*Proposal)!propuesta!por!Bert*Bos*(Eguiluz,!Introducción.!Breve!Historia,!2018).!
Alrededor!de!1995!Lie!y!Bos!se!unieron!para!definir!un!nuevo!lenguaje!aunando!lo!
mejor!de!cada!propuesta!y!lo!llamaron!CSS.!Ese!mismo!año!el!W3C!decidió!apostar!por!
el!desarrollo!y!estandarización!de!CSS!y!lo!añadió!a!su!grupo!de!trabajo!de!HTML.!
El! desarrollo! de! la! web! se! lleva! a! cabo! sobre! una! solución! hardware! con!
arquitectura! de! dos! capas,! ésta! era! la! arquitectura! más! común! y! utilizada! en! las!
computadoras! de! los! años! noventa.! También! conocida! como! arquitectura!
cliente/servidor,!requiere!de!una!interfaz!en!la!capa!del!cliente,!desde!la!que!un!usuario!
envía!solicitudes!a! través!del!protocolo!http!a!un!servidor!web,!y!este!se!encarga!de!
procesar!la!petición!y!devolver!el!recurso!solicitado,!siendo!el!cliente!el!responsable!de!
presentar!la!información.!En!la!Imagen!1,!se!muestra!el!proceso!de!comunicación!entre!
el!cliente!y!el!servidor.!
!Imagen*1.*Comunicación*en*la*arquitectura*cliente/servidor*
Los! recursos! son! estáticos,! el! servidor! simplemente! se! encarga! de! recuperarlos!
cuando!éstos!son!solicitados.!Pero!a!medida!que!avanza!el!desarrollo!de!la!web,!este!
comportamiento! estático! empieza! a! suponer! un! problema! en! cuanto! a! tiempos! de!
respuesta,! portabilidad! (ya! que! la! interfaz! era! dependiente! del! sistema! operativo)! y!
acceso!a!recursos.!!
Se!opta!por!aportar!dinamismo!a!la!parte!del!servidor;!no!solo!procesa!peticiones!
y!devuelve!recursos,!sino!que!procesa!y!también!ejecuta!las!peticiones!para!devolver!
ese!recurso.!Esto!supone!la!aparición!de!nuevos!lenguajes!de!programación!específicos!
para! la! generación!de!páginas!web!dinámicas,!que! funcionan!en!el! lado!del! servidor!
mezclando! etiquetas! de! HTML! con! sentencias! propias! de! éstos! lenguajes! de!
programación;! ejemplos! de! este! tipo! de! lenguajes! son! PHP,! ASP,! JSP,! Ruby,! etc.! El!
resultado!de!su!ejecución!devuelve!páginas!en!formato!HTML.!
Con! este! tipo! de! desarrollo,! y! situando! toda! la! carga! de! trabajo! en! el! lado! del!
servidor,!se!llega!a!un!punto!en!el!que,!vuelven!a!aparecer!problemas!de!rendimiento!y!
eficiencia!en!el!desarrollo!de!aplicaciones!y!es!necesario!que!la!parte!del!cliente!empiece!
a!asumir!responsabilidades!para!aligerar!la!carga!del!servidor.!
Así!nace!JavaScript,!el!primer!lenguaje!de!frontoend!que!se!ejecuta!en!el!navegador,!
en!vez!de!en!el!servidor.!En!1995,!Brendan*Eich*da!vida!a!lo!que!en!un!primer!momento!
se!denominó!como!Mocha,!que!luego!pasó!a!llamarse!LiveScript!y!finalmente!JavaScript.!
! Comparativa*entre*Angular*y*AngularJS.*Evolución*a*Angular*5.!
Angela!Serrano!Sánchez!! ! Página!19!!
Brendan* Eich,! ! programador! de! la! emperesa! Netscape,! crea! el! primer! lenguaje! de!
scripting! para! el! navegador!Netscape* Navigator! 2.0! adaptando! otras! tecnologías! ya!existentes!como!AWK,!Java!y!HyperTalk,!entre!otros.!Posteriormente,!Netscape! firmó!
una! alianza! con! Sun* Microsystems! para! el! desarrollo! del! nuevo! lenguaje! de!programación!y!finalmente!decide!nombrarlo!como!JavaScript!para!beneficiarse!de!la!
popularidad! que! estaba! teniendo! el! lenguaje! Java! de! Sun* Microsystems! en! aquél!entonces!(Eguiluz,!Introducción.!Breve!Historia,!2018).!
En!1996,!al!mismo!tiempo!que!se!lanzaba!la!nueva!versión!mejorada!de!JavaScript!
en! el! navegador! Netscape* Navigator! 3.0,!Microsoft! lanzó! JScript! en! su! navegador!Internet!Explorer!3.!JScript!era!una!copia!casi!exacta!de!JavaScript!al!que!le!cambiaron!
el!nombre!para!evitar!problemas!legales.!Por!este!motivo!Netscape!decidió!estandarizar!
el! lenguaje! JavaScript,! de! forma! que! a! finales! de! 1996! se! envió! la! especificación! de!
JavaScript! 1.1! al! organismo! ECMA! (European* Computer* Manufacturers* Association).!Esto!condujo!al!lanzamiento!oficial!de!la!especificación!del!estándar!ECMAo262!en!junio!
de!1997,!utilizando!el!nombre!ECMAScript!para!referirse!a!la!especificación,!nombrado!
así!para!evitar!infringir!la!marca!Java!de!Sun,!y!JavaScript!para!referirse!al!lenguaje!en!sí.!
Pero!incluso!después!de!la!aparición!de!JavaScript!como!lenguaje!que!se!ejecuta!en!
la!parte!del!cliente,!la!parte!del!servidor!seguía!teniendo!la!mayor!responsabilidad;!toda!
la! lógica! del! negocio,! el! acceso! a! datos,! la! persistencia,! etc.,! seguían! siendo!
responsabilidad!del!servidor.!Además,!que!la!lógica!de!la!aplicación!estuviese!acoplada!
a! la! vista,! hacía! muy! difícil! la! legibilidad! del! código! y! su! mantenimiento.! Incluso! la!
reusabilidad!y!la!escalabilidad!del!código!eran!características!que!se!veían!reducidas!e!
incluso!desaparecían!en!este!tipo!de! implementaciones,!haciendo!que!el!volumen!de!
código!incrementase!notablemente,!aumentando!también!su!complejidad.!
Para!solucionar!todo!lo!anterior!empiezan!a!aparecer!patrones!arquitectónicos!y!
de! diseño! a! la! hora! de! codificar! aplicaciones,! dividiendo! en! distintas! partes! las!
responsabilidades!de!la!aplicación!en!vistas,!controladores!y!modelos,!que!es!lo!que!se!
conoce!hoy!día!como!el!patrón!MVC!(ModelFViewFController)!(Hernandez,!2018).!!
!Imagen*2.*Patrón*MVC*(ModelFViewFController*
! [UPM]!Máster*en*Ingeniería*Web!
Página!20!
Siguiendo!este!patrón,!tal!y!como!se!aprecia!en!la!imagen!anterior,!el!modelo!se!
encarga! de! llevar! a! cabo! la! persistencia! y! el! acceso! a! los! datos! según! lo! requiera! el!
controlador.!Por!su!parte!el!controlador!se!encarga!de!toda!la!lógica!de!negocio;!recibe!
las! peticiones! del! usuario,! solicita! al! modelo! los! datos! para! poder! manipularlos! y!
devuelve!a!la!vista!dichos!datos!para!que!los!muestre!al!usuario.!!!
A!raíz!de!utilizar!este!patrón!en!lenguajes!de!programación!que!se!ejecutan!en!el!
servidor,! surgen! frameworks! específicos! para! cada! lenguaje,! que! se! encargan! de!simplificar!el!desarrollo!de!aplicaciones!implementando!buenas!prácticas!y!aportando!
herramientas! que! abstraen! al! desarrollador! de! tareas! complejas! como! pensar! cómo!
llevar!a!cabo!dicha!arquitectura!en!su!código,!facilitando!y!aumentando!la!rapidez!de!
desarrollo.!
Viendo!el!buen!resultado!de!utilizar!dichos!frameworks!a!la!hora!de!programar!en!
la!parte!del!servidor,!y!viendo!cómo!aumenta!la!complejidad!del!código!en!la!parte!del!
navegador!y!la!necesidad!de!adaptar!su!funcionamiento!a!distintos!dispositivos!como!
smartphones!y!tablets!empiezan!a!aparecer!los!primeros!frameworks!para!el!frontFend.!
1.2.! INTRODUCCIÓN A ANGULAR. EVOLUCIÓN DEL FRAMEWORK.
La! primera! versión! de! este! framework,! AngularJS,! aparece! en! el! año! 2010!desarrollado!e!impulsado!por!uno!de!los!gigantes!de!la!industria!de!las!tecnologías!de!la!
información,!Google!LLC.!Miško!Hevery,!empleado!de! la!compañía,!se!encontraba!en!
aquel!entonces!trabajando!en!un!proyecto!llamado!Feedback.!Este!proyecto!basado!en!Google*Web*Toolkit!(GWT),!llegó!a!alcanzar!durante!su!desarrollo!más!de!17.000!líneas!
de!código!y!el!equipo!no!estaba!satisfecho!con!su!productividad.!Por!ese!motivo!Miško!
apostó! con! su! gerente! que! podría! reescribir! el! proyecto! en! 2! semanas! utilizando! su!
framework.! Después! de! 3! semanas! y! sólo! 1.500! líneas! de! código! el! proyecto! fue!
entregado.!
Desde!ese!momento!Miško!Hevery!y!Adam!Abrons!fueron!los!encargados!de!liderar!
la! creación! y!mantenimiento! de! este! framework! de! código! abierto! para! JavaScript! y!surge!principalmente!por!la!necesidad!de!incrementar!la!productividad!en!la!experiencia!
del!desarrollo!web,!implementando!código!legible!y!de!fácil!mantenimiento!en!la!parte!
del!cliente.!!
Fue!concebido!con!la!idea!de!que!la!programación!declarativa!es!mejor!opción!para!
construir!interfaces!de!usuario!que!la!programación!imperativa,!donde!encaja!mejor!la!
lógica! de! negocio! de! la! aplicación.! Como! resultado! AngularJS! aprovecha! el! HTML!
tradicional!añadiendo!nuevas!etiquetas!a!su! lenguaje.!De!hecho,!Adam!Abrons!fue!el!
encargado!de!bautizar!al!framework!cómo!AngularJS!por!los!diples!(angle*brackets!en!inglés)!que!componen!los!elementos!de!HTML.!
Debido!a! la!gran!acogida!que!tuvo!AngularJS!y!al!crecimiento!exponencial!de!su!
utilización!y!aplicación,!quedaron!al!descubierto!carencias!del!framework!que!necesitan!
! Comparativa*entre*Angular*y*AngularJS.*Evolución*a*Angular*5.!
Angela!Serrano!Sánchez!! ! Página!21!!
ser!resueltas.!Por!este!motivo!en!el!año!2016!Google!lanza!Angular!2,!una!reescritura!
completa! del! framework! utilizando! TypeScript3! en! lugar! de! JavaScript.! Esta! nueva!versión,!da!soporte!al!desarrollo!móvil!y!su!arquitectura!está!basada!en!componentes,!
reemplazando! el! concepto! de! controlador,! que! era! hasta! el! momento! el! elemento!
principal!de!AngularJS.!
A!partir!de!Angular!2!el!equipo!de!Google!ha!seguido!sacando!nuevas!versiones!de!
éste!framework.!Por!otra!parte!AngularJS,! ya!ha! sacado! la!que! será! su!última!versión!estable,! la!
versión!1.7!.!Está!previsto!que!esta!última!versión!del!framework!entre!en!un!periodo!de!soporte!a!largo!plazo!de!tres!años,!en!Julio!de!2018.!
Siguiendo!la!evolución!de!la!nueva!rama!del!framework,!se!observa!que!la!versión!de!Angular,!pasa!directamente!de!la!2!a!la!4,!o!lo!que!es!lo!mismo,!no!existe!la!versión!
3.!Esto!se!debe!a!que,!el!equipo!de!Angular!decidió!hacer!un!cambio!en!la!nomenclatura!
de! sus! versiones! de!modo!que! cada! vez! que! se! hace! un! cambio! que!puede! generar!
conflicto!se!modifica!la!versión!(Solís,!2017).!La!manera!de!aplicar!la!nomenclatura!por!
versiones!de!Angular!se!muestra!en!la!siguiente!imagen.!
!
!Imagen*3.*Versionado*de*Angular*
Esto!fue!lo!que!sucedió!cuando!quisieron!lanzar! la!nueva!versión!de!Angular;! las!
librerías!que!componían!la!versión!dos!del!framework,!fueron!actualizándose!según!se!
iban!solucionando!errores!o!vulnerabilidades.!De!entre! todas! las! librerías! la!que!más!
modificaciones!sufrió! fue! la!de!@angular/router,! lo!que!dejaba! la!numeración!de! las!
versiones!en!las!librerías!de!la!siguiente!forma.!
!!
@angular/core!!!!!!!!!!!!!!!!!!!!!!v2.3.0!
@angular/compiler!!!!!!!!!!!!!!v2.3.0!
@angular/compilerocli!!!!!!!!!v2.3.0!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!3! TypeScript! es! un! lenguaje! de! programación! libre! y! de! código! abierto! desarrollado! y!mantenido! por!Microsoft.!Es!un!superconjunto!de!JavaScript,!que!esencialmente!añade!tipado!estático!y!se!basa!en!el!paradigma!de!programación!de!orientación!a!objetos.!
! [UPM]!Máster*en*Ingeniería*Web!
Página!22!
@angular/http!!!!!!!!!!!!!!!!!!!!!!!v2.3.0!
@angular/router!!!!!!!!!!!!!!!!!!!v3.3.0!!
!
Cuando!se!disponen!a!liberar!la!nueva!versión,!se!encuentran!con!que!la!librería!de!
router!ya!está!en!la!versión!3,!por!lo!que!sacar!la!versión!3!de!Angular,!con!la!librería!de!router! en! su! versión!4! crearía! una! gran! confusión.!Deciden!entonces! liberar!Angular!directamente!con!la!versión!de!la!mayor!dependencia,!y!así!es!como!surge!Angular!4.!
Esta!versión!es!liberada!en!Marzo!de!2017!y!es!retro!compatible!con!la!versión!2!de!
Angular.! El! principal! es! que! se! reduce! la! cantidad! de! código! generado! en! sus!
componentes,!casi!en!un!60%!en!la!mayoría!de!los!casos,!lo!que!conlleva!la!creación!de!
aplicaciones!de!forma!más!rápida!y!compacta.!
Al!ser!un!framework!en!desarrollo!constante,!que!necesita!una!rápida!evolución!
para!adaptarse!a!los!continuos!cambios!del!entorno!del!desarrollo!web,!Angular!cambia!
la!filosofía!del!ciclo!de!desarrollo!y!del!tiempo!de!vida!del!framework!haciendo!que,!en!
un!tiempo!aproximado!de!unos!seis!meses!se!libere!una!nueva!versión!de!Angular.!
De!hecho!ese!mismo!año,!en!Septiembre!de!2017,!aparece!Angular!5!y!en!Mayo!de!
2018,!se!lanza!Angular!6,!versión!sobre!la!que!versa!esta!memoria.!!
El!cambio!de!versión!en!la!nomenclatura!denota!una!incompatibilidad!o!conflicto!
de!una!versión!a!otra.!Para!solucionarlo!y!migrar!fácilmente!el!código!entre!versiones!
puede!que!sea!necesario! reemplazar!alguna! librería!obsoleta!o! refactorizar!el! código!
para!implementar!las!mejoras!introducidas!por!la!nueva!versión,!pero!la!actualización!
del! framework! no! va! a! suponer! un! cambio! de! concepto! en! la! forma! de! desarrollar!
aplicaciones!con!Angular,!como!sí!ocurrió!de!AngularJS!a!lo!que!es!ahora!Angular,!ya!que!
el!framework!se!reestructuró!completamente.!
!
! Comparativa*entre*Angular*y*AngularJS.*Evolución*a*Angular*5.!
Angela!Serrano!Sánchez!! ! Página!23!!
2.! ANGULAR
Angular!es,!más!que!la!evolución!de!AngularJS!(como!a!priori!puede!dar!a!entender!
el! nombre),! un! framework! totalmente! nuevo! desarrollado! completamente! en!
TypeScript!y!basado!en!la!especificación!del!lenguaje!ECMAScript64.!La!primera!versión*de!este!nuevo!framework!aparece!en!2016!de!la!mano!del!mismo!equipo!de!Google!que!
desarrolló!AngularJS.!!
El!rápido!crecimiento!de!Angular!JS!y!la!gran!complejidad!que!empieza!a!adquirir!el!
desarrollo!web!en! el! lado!del! cliente,! dejan! al! descubierto! carencias! del! framework,!
como! problemas! de! rendimiento,! escalabilidad,! modularidad! o! adaptabilidad! de! la!
página! en! diseños! responsive! (AngularJS! no! fue! diseñado! teniendo! en! cuenta! el!desarrollo!de!aplicaciones!para!dispositivos!móviles).!!!
Este! framework! mejorado! surge! precisamente! para! solucionar! los! problemas!
mencionados!anteriormente.!
Para!comprender!mejor! la!estructura!de!Angular,!en! los!siguientes!apartados!se!
lleva! a! cabo! un! análisis! detallado! de! la! arquitectura! del! framework! y! de! todos! los!
elementos!que!forman!parte!de!ésta.!
2.1.! ARQUITECTURA
A!diferencia!de!AngularJS,!cuya!arquitectura!se!aproxima!más!al!patrón!MVC,!más!
concretamente! a! su! variante! definida! como! MVW! (ModelFViewFWhatever),! la!documentación! oficial! de! Angular! no! hace! una!mención! explícita! del! tipo! de! patrón!
arquitectónico!que!sigue!la!estructura!de!este!framework.!En!cambio,!sí!hace!mención!
a! los! componentes! básicos! que! conforman! su! arquitectura,! los! módulos! y! los!
componentes.!
Según!se!detalla!en!la!documentación,!los!bloques!de!construcción!básicos!son!los!
módulos,!cuya!función!es!la!de!agrupar!el!código!en!conjuntos!funcionales,!es!decir,!el!
módulo! contendrá! todo! el! código! relacionado! con! una! funcionalidad! concreta! de! la!
aplicación.! Cada! módulo! se! compone! de! uno! o! varios! componentes,! elementos! de!
pantalla!que!Angular!puede!elegir!y!modificar!según!la!lógica!y!los!datos!del!programa.!
Esta! definición! encaja! en! lo! que! se! describe! cómo! ‘Arquitectura! basada! en!
componentes’.!Se!trata!de!una!rama!de!la!Ingeniería!del!software!que!se!centra!en!la!
descomposición!del!diseño!en!componentes!funcionales!o!lógicos.!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!4!ECMAScript6.!Es!la!sexta!versión*de!la!especificación!de!lenguaje!de!programación!publicada!por!ECMA!
International.!El!desarrollo!empezó!en!1996!y!estuvo!basado!en!el!popular!lenguaje!JavaScript!propuesto!
como!estándar!por!Netscape!Communications!Corporation.!
! [UPM]!Máster*en*Ingeniería*Web!
Página!24!
La!arquitectura!de!componente!gestiona!la!mecánica!de!localizar!componentes!y!
sus!interfaces,!pasando!mensajes!o!comandos!entre!componentes!y,!en!algunos!casos,!
manteniendo!el!estado!de!los!datos.!!
Esta!arquitectura!entiende!que!un!componente!de!software! individual!como!tal,!
puede!ser!un!paquete!de!software,!un!servicio!web,!un!recurso!web!o!un!módulo!que!
encapsula!un!conjunto!de!funciones!relacionadas.!En!esencia,!es!una!pieza!de!código!
diseñado!para!cumplir!con!cierto!propósito,!que!agrupa!todo!lo!relacionado!con!alguna!
funcionalidad! concreta,! cuyo! acceso! se! expone! a! través! de! interfaces! estándar!
(Microsoft,! 2009).! Los! principios! fundamentales! en! los! que! se! basa! el! diseño! de!
componentes!son!los!siguientes:!!
•!Reusabilidad.!Son!diseñados!para!ser!utilizados!en!diferentes!escenarios!e!incluso!por!diferentes!aplicaciones,!sin!embargo,!algunos!componentes!pueden!ser!diseñados!para!tareas!específicas.!!
•!Sin*contexto*especifico.!Los!componentes!son!diseñados!para!operar!en!diferentes!ambientes!y!contextos.!Información!específica!como!el!estado!de!los!datos!deben!ser!pasadas!al!componente!en!vez!de!incluirlos!o!permitir!al!componente!acceder!a!ellos.!!
•!Extensible.!Un!componente!puede!ser!extendido!desde!otro!componente!existente!para!crear!un!nuevo!comportamiento.!!
•!Encapsulamiento.! Los! componentes!exponen! interfaces!que!permiten!al!programa!usar!su!funcionalidad!sin!revelar!detalles!internos,!detalles!del!proceso!o!estado.!!
•! Independiente.! Los! Componentes! están! diseñados! para! tener! una! dependencia!mínima! con!otros! componentes.! Por! lo! tanto,! pueden! ser! instalados! en! el! ambiente!adecuado!sin!afectar!a!otros!componentes!o!sistemas.!!
Imagen*4.*Principios*de*la*arquitectura*basada*en*componentes*
Así!mismo!esta!arquitectura!presenta!los!siguientes!beneficios;!
! Comparativa*entre*Angular*y*AngularJS.*Evolución*a*Angular*5.!
Angela!Serrano!Sánchez!! ! Página!25!!
•! Facilidad* de* Instalación.! Cuando! una! nueva! versión! esté! disponible,! se! podrá!reemplazar!la!versión!existente!sin!impacto!en!otros!componentes!o!el!sistema!como!un!todo.!!
•!Costos*reducidos.!El!uso!de!componentes!de!terceros!permite!distribuir!el!costo!del!desarrollo!y!del!mantenimiento.!!
•! Facilidad* de* desarrollo.! Los! componentes! implementan! una! interfaz! bien! definida!para!proveer!su!funcionalidad,!permitiendo!el!desarrollo!sin!impactar!otras!partes!del!sistema.!!
•!Reusable.!El!uso!de!componentes!reutilizables!significa!que!pueden!ser!usados!para!distribuir!el!desarrollo!y!el!mantenimiento!entre!múltiples!aplicaciones!y!sistemas.!!
!Imagen*5.*Beneficios*de*la*arquitectura*basada*en*componentes*
Se! aprecia,! por! todo! lo! anterior,! que!Angular! pretende!mediante! su! estructura,!
aportar!todos!estos!beneficios!al!desarrollo!de!aplicaciones!web.!
Aún! así! Angular! no! se! desvincula! del! todo! del! patrón!ModelFViewFController! y!derivados.! En! el! glosario! de! términos! del! framework,! para! el! componente! se! hace!
mención!explícita!a!los!patrones!MVC!y!MVVM,!haciendo!una!correlación!directa!entre!
los!componentes!de!Angular,!y!los!Controllers!y!las!VistasoModelo!respectivamente!de!
los!patrones!anteriores.!
Pero,! aunque! los! módulos! y! los! componentes! son! los! elementos! básicos! de! la!
estructura!del!framework,!no!son!los!únicos!que!conforman!la!arquitectura!de!Angular.!
También!existe!lo!que!se!conoce!como!servicios,!que!proporcionan!una!funcionalidad!
específica! que! no! está! directamente! relacionada! con! las! vistas.! Los! proveedores! de!
servicios!pueden!inyectarse!en!los!componentes!como!dependencias,!haciendo!que!su!
código!sea!modular,!reutilizable!y!eficiente.!!
Tanto! los! componentes! como! los! servicios! son! simplemente! clases,! con!
decoradores!que!marcan!su!tipo!y!proporcionan!metadatos!que!indican!a!Angular!cómo!
deben!utilizarse.!
Los!metadatos!del!componente!asocian!una!clase!con!una!plantilla!que!define!una!
vista.! Una! plantilla! combina!HTML! común! con! directivas! y! etiquetas! de! angular! que!
permiten! al! framework! modificar! la! plantilla! HTML! antes! de! renderizarla! para! su!
visualización.!
! [UPM]!Máster*en*Ingeniería*Web!
Página!26!
Los! metadatos! un! servicio! brindan! la! información! que! Angular! necesita! para!
ponerlo! a! disposición! de! los! componentes! a! través! de! la! inyección! de! dependencias!
(conocido!como!DI,!Dependency*Injection,!por!sus!siglas!en!inglés).!Todos! los! elementos! de! Angular!mencionados! en! este! punto! se! desarrollan! en!
detalle!en!los!siguientes!apartados!de!este!documento.!
2.2.! NGMODULES Y BOOTSTRAPPING
Como!se!acaba!de!indicar!en!el!apartado!anterior,!uno!de!los!elementos!básicos!en!
la!arquitectura!de!Angular!son!los!módulos,!o!NgModule!tal!como!se!denominan!en!el!
framework.!Los!módulos!son!la!estructura!en!la!que!se!agrupa!todo!lo!relacionado!con!
una!funcionalidad!concreta!de!la!aplicación.!En!particular,!toda!aplicación!que!se!quiera!
desarrollar! bajo! Angular,! debe! tener! como!mínimo! un!módulo,! que! será! el! módulo!
principal!y!el!que!inicializará!la!aplicación.!
La! configuración! y! propiedades! del! NgModule! principal! son! necesarias! para!
compilar!y!ejecutar!las!distintas!partes!de!la!aplicación!e!indicar!al!framework!cómo!debe!
iniciarse!sin!necesidad!de!entradas!externas.!Este!proceso!se!denomina!Bootstrapping.!!
2.2.1.! BOOTSTRAPPING
Para!inicializar!una!aplicación!Angular,!es!necesario!cargar!el!módulo!principal!de!
la!aplicación.!Esto!se!realiza!mediante!la!sentencia;!
platformBrowserDynamic().bootstrapModule(AppModule) .catch(err => console.log(err));
!
Donde! AppModule! es! el! nombre! de! la! clase! que! recibe! dicho! módulo.! Esta!
sentencia!se!ubica!en!una!clase!específica!generada!automáticamente!con!Angular!CLI!
(instalador! de! Angular),! normalemente!main.ts,! que! será! el! punto! de! entrada! a! la!aplicación.!
2.2.2.! EL DECORADOR @NGMODULE
Los!módulos!de!Angular,!son!clases!marcadas!con!el!decorador!@NgModule.!Este!
decorador! proporciona! a! la! clase! los! metadatos! con! la! información! necesaria! para!
indicar! al! framework! cómo! compilar! la! plantilla! de!un! componente! y! cómo! crear!un!
inyector!en!tiempo!de!ejecución.!!
Su!principal!función!es!describir!cómo!encajan!y!trabajan!jutas!las!distintas!partes!
de! la! aplicación;! identifica! los! componentes,! directivas! y! pipes! propios! del! módulo,!
haciendo!que!sean!públicos,!para!que!los!componentes!externos!puedan!usarlos,!agrega!
! Comparativa*entre*Angular*y*AngularJS.*Evolución*a*Angular*5.!
Angela!Serrano!Sánchez!! ! Página!27!!
proveedores!de!servicios,!etc.!Todos!los!elementos!que!se!incluyan!en!este!decorador!
deben!importarse!previamente!en!el!módulo.!
Esta!anotación!contiene!una!serie!de!propiedades!que!indican!al!framework!cómo!
debe!realizar!todas!las!funciones!anteriores.! @NgModule({
declarations: [], !Componentes de la aplicación contenidos en el módulo
imports: [], !Import de otros módulos que necesita utilizar la aplicación
exports: [], entryComponents: [], providers: [], !Proveedores de servcios bootstrap: [] !Componente root, punto de entrada de la
aplición })
!
En!los!siguientes!apartados!se!detallan!los!más!comunes!a!la!hora!de!crear!módulos!
en!Angular.!
2.2.2.1.! EL ARRAY DECLARATIONS
En!este!array!se!incluyen!los!componentes,!directivas!y!pipes!que!forman!parte!del!
módulo.!!
Es! importante! señalar! que! cada! uno! de! los! elemento! mencionados! sólo! podrá!
pertenecer! a! un! único!módulo.! Las! clases! declaradas! en! un!módulo! concreto! serán!
invisibles!a!elementos!que!pertenezcan!a!otros!módulos.!Para!que!puedan!ser!visibles!al!
exterior,! el! módulo! debe! ser! exportable,! de! forma! que! pueda! importarse! como!
dependencia!de!otro!módulo.!
2.2.2.2.! EL ARRAY IMPORTS
Aquí!será!donde!se! indique!qué!otros!módulos!van!a!ser!necesarios!para!que!el!
módulo! en! cuestión! funcione! correctamente.! Angular! aporta! una! gran! cantidad! de!
módulos! predefinidos! como! el! BrowserModule,! el! FormsModule! o! el! HttpModule,!
aunque!siempre!se!podrán!desarrollar!módulos!propios,!como!se!verá!en!el!apartado!de!
NgModules!de!Angular.!
2.2.2.3.! EL ARRAY PROVIDERS
En! esta! propiedad! se! incluirán! todos! los! servicios! que! podrán! ser! inyectados! y!
utilizados!por!el!resto!de!elementos!de!la!aplicación.!
! [UPM]!Máster*en*Ingeniería*Web!
Página!28!
2.2.2.4.! EL ARRAY BOOTSTRAP
Por!último,!pero!no!por!ello!menos!importante,!el!array!bootstrap.!Este!array!será!
el! encargado! de! indicar! a! Angular! qué! componente! será! el! primero! en! ejecutarse,!
normalmente!el!componente!raíz.!!
2.2.3.! MÓDULOS CARACTERÍSTICOS
Según! la!documentación!de!Angular,! los!módulos! son!una!excelente!manera!de!
organizar! una! aplicación;! consolidan! componentes,! directivas,! pipes! y! servicios! en!conjuntos!de!bloques!coherentes,!e!incluso!puede!ampliarse!su!funcionalidad!mediante!
el!uso!de!bibliotecas!externas.!
Atendiendo!al! tipo!de! funcionalidad!que!vaya!a!cubrir!el!módulo!a! implementar!
puede!englobarse!en!una!de!las!siguientes!categorías:!
oDe!dominio:!Se!centran!principalmente!en!un!dominio!particular!de!la!aplicación,!
es!decir,!un!área!concreta!de!funcionalidad.!Se!componen!de!elementos!declarativos;!
componentes,!directivas…!Rara!vez!deberían!incluir!proveedores!en!su!definición.!
oEnrutado:!Son!módulos!cuyos!componentes!principales! son! los!objetivos!de! las!
rutas!de!navegación!del!enrutador.!No!exportan!nada!porque!sus!componentes!nunca!
aparecen!en!la!plantilla!de!un!componente!externo.!
oEnrutamiento:!Se!componen!de!las!rutas!de!navegación!de!la!aplicación.!Definen!
las!rutas!y!agregan!la!configuración!al!módulo!principal.!
oServicio:! Proporcionan! servicios! de! utilidad! como! acceso! a! datos! y!mensajería.!
Idealmente,! consisten! completamente! en! proveedores! y! no! tienen! elementos!
declarativos.! El!HttpClientModule! de! Angular! es! un! buen! ejemplo! de! un!módulo! de!
servicio.!
FWidget:!Un!módulo!de!widget!hace!que!los!componentes,!directivas!y!pipes!estén!disponibles!para!módulos!externos.!Consisten!enteramente!en!elementos!declarativos!
y!rara!vez!deben!tener!proveedores.!
En! la! creación! de! módulos! suele! ser! bastante! difícil! que! éstos! encajen!
perfectamente! en! una! de! las! definiciones! anteriores,! por! lo! que! lo! más! común! es!
encontrar!módulos!híbridos,!que!combinan!dos!o!más!categorías!de!las!especificadas.!
Para!poder!utilizar!el!módulo!creado!en!otras!partes!de! la!aplicación,!éste!debe!
exportarse,! para! importarlo! en! el! módulo! correspondiente.! Estos! módulos! tendrán!
además! la!misión!de!exportar! los! componentes,!directivas!o!pipes*que!necesiten! ser!usados!por!otros!elementos!de!la!aplicación!fuera!del!módulo.!Para!ello,!a!los!metadatos!
del! decorador! @NgModel! se! le! puede! indicar! en! la! propiedad! exports! aquellos!elementos!que!van!ser!utilizados!por!elementos!externos.! @NgModule({
exports: [] })
! Comparativa*entre*Angular*y*AngularJS.*Evolución*a*Angular*5.!
Angela!Serrano!Sánchez!! ! Página!29!!
2.2.4.! NGMODULES DE ANGULAR
Hay!funcionalidad!que!suele!ser!común!en!el!desarrollo!de!aplicaciones!web,!como!
la!conexión!al!servidor,!el!enrutamiento!y!navegación!entre!las!páginas!de!la!aplicación,!
o!la!creación!de!formularios,!entre!otros.!!
Angular! simplifica! el! uso! de! esta! funcionalidad! proporcionando! librerías! ya!
implementadas! que! ponen! a! disposición! del! desarrollador! múltiples! herramientas! y!
métodos!para!aplicar!dicha!funcionalidad!en!la!aplicación.!
A! continuación! se! muestra! una! relación! con! los! NgModules! más! comúnmente!
usados!de!Angular.!
!
Módulo* Librería* Función*
BrowserModule*@angular/platformo
browse!
Para!ejecutar!la!aplicación!en!
el!navegador!web!
CommonModule* @angular/common!Para! utilizar! las! directivas!
predefinidas!del!framework!
FormsModule* @angular/forms!Para! construir! formularios!
dinámicos!
ReactiveFormsModule* @angular/forms!Para! construir! formularios!
reactive.!
RouterModule* @angular/router!Para! el! enrutamiento! y!
navegación!de!la!aplicación!
HttpClientModule* @angular/common/http! Para!conectar!con!el!servidor!
2.3.! COMPONENTES
Podría! decirse! que! los! componentes! son! la! espina! dorsal! del! framework.! Toda!aplicación!debe!tener!al!menos!un!componente!principal,!denominado!componente!raíz!
que!es!el!encargado!de!conectar! la! jerarquía!de!componentes!de! la!aplicación!con! la!
página!DOM!(Document*Object*Model)!y!que!será!el!punto!de!entrada!a!la!aplicación.!Un! componente! es! básicamente! un! conjunto! de! etiquetas,!metadatos,! objetos,!
atributos! y! métodos,! que! combinados! son! capaces! de! crear! un! Widget* UI! (User*Interface).!Todo!componente!está!compuesto!por!un!decorador!o!también!denominado!
anotación!o,!una!vista!y!un!controlador,!y!contendrá!en!sí!mimo!información!importante!
sobre! su! comportamiento;!qué!datos!necesita! cómo!entrada,!qué!eventos!emitirá!al!
resto!de!componentes,!cómo!se!renderizará!su!vista!y!cuales!son!sus!dependencias!con!
el!resto!de!elementos!de!la!aplicación.!
La!estructura!de!un!componente,!es!la!que!se!muestra!en!la!Imagen!6.!
! [UPM]!Máster*en*Ingeniería*Web!
Página!30!
!Imagen*6.*Estructura*de*un*componente*en*Angular*
2.3.1.! METADATOS, DECORADORES Y EL DECORADOR
@COMPONENT
Los!metadatos!en!los!componentes!indican!a!Angular!dónde!encontrar!los!bloques!
y!elementos!que!necesita!para!crear!y!mostrar!el!componente!y!su!vista.!En!particular,!
asocia!una!plantilla!al!componente,!bien!por!referencia!o!directamente!en!el!código.!Las!
anotaciones! son! las! encargadas! de! proveer! estos! metadatos! al! framework! para!combinar!todos!los!elementos!que!conforman!la!aplicación,!y!hacer!que!ésta!funcione!
correctamente.!
En!el!componente,! la!anotación!principal!y!más! importante!es!@Component.!Se!ubica!encima!de!la!definición!de!la!clase!y!se!encarga,!entre!otras!cosas,!de!configurar!
cómo!puede!ser!referenciado!el!componente!por!otros!elementos!de!la!aplicación,!las!
dependencias!con!otros!servicios,!o!cómo!va!a!mostrar!los!datos!que!lo!forman.!
Entre!las!distintas!opciones!que!configuran!el!componente,!las!principales!son;!
•! selector:! ! Etiqueta! que! se! asigna! al! componente! y! con! la! que! éste! será!referenciado!en!las!plantillas!de!otros!componentes.!
•! template/templateUrl:!Especifica!la!plantilla!del!componente.!En!el!primer!caso!la! plantilla! está! integrada! directamente! en! el! código.! Esta! práctica! es!recomendable!en!el!caso!de!plantillas!simples.!En!el!segundo!caso,!se!especifica!la!ruta!relativa!al!fichero!que!contiene!la!plantilla.!
•! styles/styleUrls:!Especifica!los!estilos!de!la!plantilla.!Del!mismo!modo!que!en!la!definición!de!plantillas,!en!el!primer!caso,!la!definición!de!estilos!va!dentro!de!un!bloque!entrecomillado!directamente!en!el!componente,!y!en!el!segundo,!la!hoja!de! estilos! se! encuentra! en! una! ruta! relativa,! a! la! que! el! componente! hace!referencia.!
La!estructura!más!común!del!decorador!suele!ser!la!siguiente;!
!
! Comparativa*entre*Angular*y*AngularJS.*Evolución*a*Angular*5.!
Angela!Serrano!Sánchez!! ! Página!31!!
@Component({
selector: ‘etiqueta-del-componente’ templateUrl: [‘./app.component.html’] styleUrl: [‘./app.component.css]
}) !
Existen! otras! propiedades! que! también! pueden! aplicarse! a! la! definición! de!
componentes,!aunque!suelen!ser!funcionalidades!más!avanzadas!(Clow,!2018);!
•! animations:!Lista!de!animaciones!del!componente.!•! changeDetection:!Estrategia!de!detección!de!cambios!usada!por!el!componente.!•! encapsulation:! Estrategia! de! encapsulamiento! de! estilos! utilizada! por! el!
componente.!•! entryComponents:!Lista!de!componentes!que!se!insertan!dinámicamente!en!la!
vista!del!componente.!•! exportAs:!Nombre! con!el!que! se!exporta! la! instancia!del! componente!en!una!
plantilla.!•! inputs:!Lista!de!propiedades!de!la!clase!que!serán!vinculadas!como!propiedades!
de!entrada!en!el!componente.!•! interpolation:! Definición! de! las! marcas! que! aplicarán! la! interpolación! en! la!
plantilla!del!componente,!sobrescribirán!las!marcas!por!defecto!{{!}}.!•! outputs:!Lista!de!propiedades!de!la!clase!que!expondrán!eventos!de!salida!que!
podrán!ser!suscritos!por!otros!componentes.!•! providers:!Lista!de!proveedores!de!servicios!disponibles!para!el!componente!y!
sus!componentes!hijos.!•! queries:!Configura!queries!que!pueden!ser!inyectadas!en!el!componente.!
2.3.2.! PLANTILLAS Y DATA BINDING
Para! aquellos! que! estén! familiarizados! con! los! patrones! de! MVC! (ModelFViewFController)!ó!MVVM!(ModelFViewFViewModel),!las!plantillas!de!Angular!definidas!en!los!componentes!representan!las!vistas!de!la!aplicación,!es!decir,!son!las! interfaces!de!la!
aplicación! con! las! que! interactuará! un! usuario! para! manipular! la! información! del!
componente!al!que!esté!asociada!la!vista.!La!información!para!renderizar!la!plantilla!la!
proporcionan! las! opciones! de! template! ó! templateUrl,! según! se! haya! indicado! en! la!configuración!del!componente!a!través!de!la!anotación!@Component.!
Estas! plantillas! tienen! el! aspecto! de! páginas! HTML,! salvo! porque! combina! las!
etiquetas!nativas!de!este!lenguaje!de!marcado,!con!etiquetas!propias!de!la!sintaxis!de!
Angular,! que! pueden! modificar! los! elementos! HTML! antes! de! ser! visualizados,!
dependiendo!de!la!lógica!de!la!aplicación,!su!estado!y!de!los!datos!del!DOM.!!
Angular! permite! extender! el! lenguaje! HTML! con! nuevas! etiquetas! referentes! a!
componentes!y!directivas.!Elementos!básicos!de!manipulación!en!la!sintaxis!de!Angular,!
son! la! técnica!de!data*binding,!para!coordinar! la! información!entre! la!aplicación!y!el!
DOM,!los!pipes!ó!filtros,!que!transforman!la!información!antes!de!ser!visualizada!o!las!
! [UPM]!Máster*en*Ingeniería*Web!
Página!32!
directivas,!que!aplican!la!lógica!del!componente!a!la!vista.!Todos!ellos!serán!tratados!en!
detalle!más!adelante.!
Aunque!HTML!es! la!sintaxis!utilizada!por!Angular!para!definir! las!plantillas,!cabe!
destacar! que! no! todas! las! etiquetas! de! este! lenguaje! tienen! cabida! en! Angular,!
particularmente!está!prohibido!el!uso!del!tag!<script>!para!evitar!ataques!de!inyección!
de!scripts.!Si!esta!etiqueta!es!encontrada!en!alguna!de!las!plantillas,!es!ignorada!y!un!warning!aparecerá!en!la!consola!del!navegador.!Otras!etiquetas!como!<html>!o!<body>!
dejan!de!tener!sentido,!ya!que!no!representan!un!papel!importante!en!la!plantilla.!
2.3.2.1.! EXPRESIONES
Aunque!la!definición!de!data*binding,!y!todos!los!tipos!de!enlazado!de!datos!que!existen! en! Angular! serán! explicados! más! adelante! (apartado! de! Data! Binding),! es!
necesario!hacer!referencia!a!este!concepto,!ya!que!es!precisamente!esta!técnica!la!que!
utiliza!Angular!para!coordinar!los!datos!que!se!van!a!mostrar!en!la!vista,!dependiendo!
de!lo!que!indique!la!lógica!del!componente.!
En!las!plantillas,!todos!los!datos!mostrados!por!la!técnica!de!data*binding!utilizan!expresiones!que!producen!un!valor.!Angular!ejecuta!las!expresiones!y!asigna!su!valor!a!
una!propiedad!objetivo;! como!puede! ser!un!elemento!HTML,!un! componente!o!una!
directiva.!
La!forma!más!conocida!de!evaluar!expresiones!en!las!plantillas!(y!que!ya!se!dio!a!
conocer!en!AngularJS)!es!la!interpolación;!cuya!notación!es!{{expresión}}.!!
El!contexto!de!la!expresión!suele!corresponderse!con!la!instancia!del!componente,!
es!decir,!la!lógica!del!componente!contendrá!un!atributo!de!instancia,!que!será!el!que!
posteriormente!se!evalúe!como!expresión!en!la!vista.!Aunque!una!expresión!también!
puede!hacer!referencia!a!propiedades!del!contexto!de!la!plantilla!tales!como!variables!
de!entrada,!o!variables!de!referencia.!
// element es una variable de entrada // elements es una propiedad de instancia <div *ngFor="let element of elements">{{element.name}}</div> // elementInput es una variable de referencia <input #elementInput> {{elementInput.value}}
!
Las!expresiones!son!una!herramienta!muy!potente!en!la!creación!de!aplicaciones!
Angular.! Por! este!motivo!deben! tenerse!en! cuenta!una! serie!de!pautas! a! la!hora!de!
aplicar!las!expresiones:!
-! Sin!efectos!secundarios!visibles:!Una!expresión!no!debe!cambiar!el!estado!de!otras!propiedades!de!la!aplicación.!
-! Rápida!ejecución:!Angular!ejecuta! las!expresiones!tras!cada!ciclo!de!detección!de!
cambios.! Éste! ciclo! es! lanzado! repetidas! veces! dentro! de! la! ejecución! de! la!
! Comparativa*entre*Angular*y*AngularJS.*Evolución*a*Angular*5.!
Angela!Serrano!Sánchez!! ! Página!33!!
aplicación,!por!lo!que!las!expresiones!deben!evaluarse!rápidamente!para!mejorar!la!
experiencia!de!interacción!del!usuario!
-! Simplicidad:!Se!deben!evitar!expresiones!de!plantilla!complejas.!-! Idempotencia:! Las! expresiones! idempotentes! son! ideales! porque! están! libres! de!
efectos! secundarios! y! mejoran! el! rendimiento! en! la! detección! de! cambios! de!Angular.!!!Si!no!se!siguen!estas!pautas!el!funcionamiento!de!la!aplicación!podría!verse!afectado.!
2.3.2.2.! INSTRUCCIONES
Las! instrucciones! de! plantilla! responden! a! los! eventos! lanzados! por! los!
componentes! o! directivas.! Al! contrario! que! las! expresiones,! las! instrucciones! sí! que!
deben! tener!un!efecto! secundario!en! los!elementos!de! la!plantilla,!de!esta! forma!es!
como!se!actualiza!el!estado!de!la!aplicación!tras!una!acción!del!usuario.!!
De!forma!similar!a!las!expresiones,!las!instrucciones!solo!pueden!hacer!referencia!
a!lo!que!hay!en!el!contexto!de!la!sentencia!que!suele!ser!la!instancia!del!componente,!
aunque!también!puede!hacer!referencia!al!propio!contexto!de!la!plantilla.!
Debe! evitarse! escribir! instrucciones! de! plantilla! complejas.! Como! norma,! éstas!
sentencias!deben!ser!llamadas!a!métodos!o!asignaciones!simples!a!propiedades.!!
2.3.2.3.! DATA BINDING
Una!vez!visto!cómo!debe!estructurarse!y!escribirse!una!plantilla,!y!cómo!Angular!
comunica!los!datos!del!componente!con!su!vista!a!través!de!lo!que!ya!se!ha!definido!
como! data* binding,! en! este! apartado! se! pretende! ampliar! la! descripción! de! este!
concepto! y! los! tipos! de! data* binding! que! proporciona! Angular! para! cubrir! las!necesidades!de!comunicación!en!los!componentes.!
Sin!un!framework,!el!programador!sería!el!responsable!de!colocar!los!valores!de!los!
datos!en!los!controles!del!documento!HTML,!transformar!las!respuestas!del!usuario!en!
acciones!y!actualizar!los!valores!de!forma!manual.!Hacer!ese!desarrollo!puede!llegar!a!
convertirse!en!una!pesadilla,! siendo!además!propenso!a!producir!múltiples!errores!y!
dificultando!la!lectura!del!código.!
Para!dar!solución!a!lo!anterior!Angular!provee!al!framework!de!lo!que!se!denomina!
como!data*binding;!un!mecanismo!que!coordina!lo!que!el!usuario!puede!ver,!con!los!
valores!de!la!aplicación.!Hay!dos!tipos!de!comunicación!entre!los!datos!del!componente!
y!su!vista;!OneFway*data*binding*y!TwoFway*data*binding.**Cuando!la!información!que!se!intercambia!viaja!en!una!única!dirección,!se!utiliza!el!
denominado!OneFway*data*binding.!Este!concepto,!se!subdivide!a!su!vez!en!otras!dos!categorías:!de!la!lógica!a!la!vista!(al!DOM),!o!de!la!vista!a!la!lógica!del!componente!(desde!
el!DOM).!Si!el!intercambio!se!produce!en!ambas!direcciones,!entonces!entra!en!acción!
el!twoFway*data*binding.!!
! [UPM]!Máster*en*Ingeniería*Web!
Página!34!
En!total,!existen!cuatro!mecanismos!de!data*binding,!representados!por!distintos!tipos!de!etiquetas.!Cada!uno!de!ellos!tendrá!una!dirección!de!comunicación!con!el!DOM,!
como!puede!verse!representado!en!la!Imagen!6!y!que!se!detallan!a!continuación.!
!
!Imagen*7.*Tipos*de*Data*Binding*
ONE-WAY DATA BINDING
Interpolación
El! primer! flujo! representado! va! del! componente! al! DOM! y! ya! se! ha! definido!
anteriormente.!Se!trata!de!la!interpolación,!es!decir,!evaluar!el!valor!de!una!expresión!
entre!llaves!para!mostrar!el!resultado!en!la!vista!sin!modificar!su!valor,!y!que!suele!ser!
el! nombre! de! una! propiedad! del! componente! (la! instancia! de! una! variable! del!
componente).!Angular!reemplaza!la!expresión!con!el!string!del!valor!correspondiente!a!esa!propiedad.!
En! líneas!más!generales,!Angular!primero!evalúa!el! contenido!de! la!expresión!y!
luego!lo!convierte!a!string,!ya!que!una!expresión!no!sólo!se!utiliza!con!propiedades!del!componente,! también! puede! contener! llamadas! a! métodos,! o! expresiones! escritas!
directamente!dentro!de!las!llaves.!
Property binding
Este!segundo!tipo,!al!igual!que!la!interpolación,!también!viaja!con!la!información!
hacia!el!DOM.!Se! trata!del!denominado!property*binding* (enlace!de!propiedad)! y! se!produce! cuando! se! asigna! el! valor! de! una! expresión! (valor! entrecomillado)! a! una!
propiedad!del!modelo!(representado!entre!corchetes![]).!La!mayoría!de!las!veces!esta!
propiedad!es!la!propiedad!de!una!directiva!o!la!de!un!componente.!!!
En! este! tipo! de! comunicación! se! recomienda! seguir! las! guías! de! expresiones! e!
instrucciones,!para!evitar!efectos!secundarios!no!deseados!en!la!aplicación!y!ceñir!su!
utilización! a! propiedades! y! métodos! que! devuelven! valores! simples.! También! debe!
tenerse!en!cuanta!que!el!tipo!de!valor!que!retorne!la!expresión!debe!ser!del!tipo!que!
espera!la!propiedad.!Por!ejemplo,!no!se!puede!retornar!un!elemento!de!tipo!string,!si!lo!que!espera!la!propiedad!es!un!objeto.!
! Comparativa*entre*Angular*y*AngularJS.*Evolución*a*Angular*5.!
Angela!Serrano!Sánchez!! ! Página!35!!
Las!dos!situaciones!anteriores!representan!el!mismo!modelo!de!comunicación!oneFway*data*binding!del!componente!al!DOM,!¿cómo!distinguir!entonces!cual!utilizar!en!
cada!caso?!Es!sencillo,!si!el!valor!que!se!quiere!asignar!a!la!propiedad!es!de!tipo!string,!ambos!son!igualmente!válidos,!aunque!por!simplicidad!de!lectura!y!por!normalización!
en!el!código!se!suele!utilizar!la!interpolación,!si!el!valor!a!retornar!es!de!cualquier!otro!
tipo,!suele!utilizarse!el!método!de!property*binding.!Data$Binding$de$Atributos,$Clases$y$Estilos$Cuando!lo!que!se!quiere!es!modificar!un!elemento!del!DOM,!como!un!atributo,!una!
clase! o! un! estilo! en! vez! de! una! propiedad! del! componente,! la! sintaxis! de! plantilla!
proporciona!otros!tipos!de!OneFWay*Data*Binding!.!Se!puede!establecer!el!valor!de!un!atributo!directamente!con!un!enlace!de!atributo,!
éste!es!el!único!enlace!que!crea!y!establece!un!atributo.!Se!recomienda!siempre!que!sea!
posible!utilizar!enlaces!de!tipo!property*binding,!excepto!en!la!situaciones!en!las!que!no!existe!una!propiedad!a!la!que!agregar!el!enlace.!
La!sintaxis!de!enlace!de!atributo!es!parecida!a!la!de!property*binding;!en!lugar!de!una!propiedad,!entre!corchetes!irá!una!cadena!con!el!prefijo!attr!seguido!de!un!punto!y!
el!nombre!del!atributo;!
<td [attr.colspan]="1 + 1">One-Two</td>
!
!
Del!mismo!modo!que!en!el!caso!anterior,!también!pueden!enlazarse!los!atributos!
especiales!classes!y!style!en!los!elementos!del!DOM.!El!primero!de!estos!dos!atributos!
se! utiliza! para! cambiar! la! clase! CSS! de! un! elemento.! La! sintaxis! cambia! y! en! vez! de!
[attr.nombreDelAtributo]!se!utiliza!la!notación![class.nombreDeLaClaseCSS].!Lo!mismo!
ocurre!con!el!atributo!style,!que!normalmente!define!las!propiedades!de!estilo!de!un!
elemento!concreto!y!su!sintaxis!es![style.propiedadCSS].!
Estos!dos!últimos!casos!en!concreto,!pueden!ser!útilies!cuando!sólo!es!necesario!
modificar!una!clase!o!estilo!concreto,!pero!para!modificar!varias!clases!o!estilos!al!mismo!
tiempo! se! recomienda! utilizar! las! directivas!NgClass! y!NgStyle! respectivamente.! (ver!
apartado!de!Directivas!de!atributo!predefinidas).!!!
Event binding
En!el!tercer!flujo,!el!intercambio!de!información!también!es!de!sentido!único,!pero!
en!este!caso!la!dirección!es!contraria!a!los!dos!anteriores.!Es!decir,!viaja!de!los!elementos!
del!DOM!a!la!lógica!del!componente.!Se!denomina!event*binding,!y!es!el!que!se!encarga!de!proporcionar!al!usuario!interacción!con!las!vistas!de!la!aplicación.!
La!única!forma!de!conocer!las!intenciones!del!usuario,!es!a!través!de!los!eventos!
que! se! lanzan! tras! la!ejecución!de!una!determinada!acción;! como!un!click! del! ratón,!pulsar! teclas! del! teclado,! etc.! Para! ello! Angular! proporciona! el! event* binding,! que!consiste! en! declarar! un! evento! objetivo,! que! “escuchará”! la! petición! del! usuario! y!
lanzará! una! determinada! acción! para! modificar! propiedades! del! modelo,! cuando! la!
! [UPM]!Máster*en*Ingeniería*Web!
Página!36!
llamada!al!evento!en!cuestión!se!produzca.!La!sintaxis!de!este!flujo!se!representa!cómo!
(evento)=”metodo()”.! Tras! escuchar! la! acción! solicitada! por! el! usuario,! se! lanzará! el!
método!asociado,!que!se!representa!entrecomillado!a!la!derecha!de!la!expresión,!para!
realizar!modificaciones!sobre!uno!o!varios!elementos!del!modelo.!
En!el!event*binding,!Angular!configura!un!controlador!de!eventos!para!el!evento!objetivo.! Cuando! se! levanta! el! evento,! el! controlador! ejecuta! la! declaración! de! la!
plantilla.!La!declaración!de!la!plantilla!generalmente!implica!un!receptor,!que!realiza!una!
acción!en!respuesta!al!evento,!como!almacenar!el!valor!de!un!elemento!de!control!HTML!
en!un!modelo.!El!enlace!transmite!información!sobre!el!evento,!incluidos!los!valores!de!
los!datos,!a!través!de!un!objeto!de!evento!llamado!$event.!!El!tipo!del!objeto!del!evento!está!determinada!por!el!evento!objetivo.!Si!el!evento!
objetivo!es!un!evento!de!un!elemento!nativo!del!DOM,!entonces!$event!es!un!objeto!de!evento!DOM.!Cuando!esto!sucede,!la!documentación!de!Angular!recomienda!evitar!el!
uso! de! esta! práctica! a! la! hora! de! desarrollar! aplicaciones! con! Angular;! utilizar! este!
objeto,! implica! enviar! el! evento! completo! del! DOM! al! componente,! es! decir,! al!
componente! le! está! llegando! mucha! más! información! sobre! la! implementación! del!
HTML!de!la!que!necesita.!Esto!rompe!la!separación!de!preocupaciones!entre!la!plantilla!
(lo!que!el!usuario!ve)!y!el!componente!(como!procesa!los!datos!del!usuario!la!aplicación).!!
Para! solucionar! este! problema! se! propone! el! uso! de! variables! de! referencia! de!
plantilla.!
Variables de referencia de plantilla
Una!variable!de!referencia!de!plantilla!suele!referenciar,!como!su!nombre!indica,!a!
un!elemento!DOM!dentro!de!una!plantilla,!aunque!también!podrías!ser!una!referencia!
a!un!componente!o!directiva,!por!ejemplo.!!
Para! declarar! una! variable! de! referencia! en! un! elemento! del! DOM! se! utiliza! el!
símbolo! hash(#),! seguido! del! nombre! que! se! le! quiera! asignar.! Por! ejemplo! en! un!
elemento!<input!#username>,!username!será!la!variable!de!referencia.!A!través!de!este!nombre,! se!podrá!acceder!al!valor!del!elemento!<input>!desde!cualquier!parte!de! la!
plantilla.!
El!alcance!de!una!variable!de!referencia!es!el!contexto!completo!de!la!plantilla,!por!
lo!que!no!se!debe!definir!el!mismo!nombre!de!variable!más!de!una!vez!en! la!misma!
plantilla!o!su!valor!en!tiempo!de!ejecución!será!impredecible.!
TWO-WAY DATA BINDING
Por! último,! una! de! las! características! principales! de! Angular,! el! twoFway* data*binding.!Este!flujo!proporciona!comunicación!bidireccional!entre!la!vista!y!la!lógica!del!
componente.!Esta!formado!por!la!combinación!de!las!técnicas!property*binding!e!event*binding!y!su!representación!también!es!una!combinación!de!ambas![()].!
Como! dato! curioso,! por! lo! característico! de! su! notación! esta! representación!
también!se!conoce!como!Banana*in*a*box.!!
! Comparativa*entre*Angular*y*AngularJS.*Evolución*a*Angular*5.!
Angela!Serrano!Sánchez!! ! Página!37!!
En!el!twoFway*data*binding,!el!valor!de!una!propiedad!viaja!desde!el!componente!
hasta! la! vista! como! con! el! enlace! de! propiedad.! Los! cambios! del! usuario! sobre! esta!
propiedad! vuelven! entonces! al! componente,! restableciendo! la! propiedad! al! último!
valor,! como! con! el! enlace! de! eventos.! El! flujo! queda! representado! en! la! siguiente!
imagen.!
!
!Imagen*8.*TwoFway*data*binding*
2.3.3.! COMUNICACIÓN ENTRE COMPONENTES
Como!se!ha!podido!ver!a!lo!largo!de!todo!el!apartado!anterior,!Angular!proporciona!
los!mecanismos!necesarios!para!que!se!produzca! la! comunicación!entre! la! lógica!del!
componente!y! su!vista.!Pero!el! intercambio!de! información!no! se! reduce!a!un!único!
componente.! Los! distintos! componentes! de! la! aplicación! deben! poder! comunicarse!
entre!sí.!
Además!de! importar! los!componentes!con! los!que!se!tiene!alguna!dependencia,!
para!poder!obtener!y!manipular!propiedades!de!éstos,!Angular!provee!al!framework!de!
varias! anotaciones,! cuyos! metadatos! proporcionan! la! información! que! necesita! la!
aplicación!para!cumplir!con!este!cometido.!
Un!componente!no!podrá!acceder!a!propiedades!de!otros!componentes!sin!estas!
anotaciones.!El!motivo!principal!es!evitar!comportamientos!indeseados!en!la!aplicación.!
Cuando!una!aplicación!crece,!y!con!ella!sus!dependencias,!se!pierde!el!control!de!qué!
componentes!harán!uso!de!qué!propiedades.!Este!tratamiento!hace!que!se!restrinjan!
determinados!accesos!que!de!otro!modo!podrían!afectar!al!correcto!funcionamiento!de!
la!aplicación.!
La!primera!de!estas!anotaciones!es!@Input,!que!aplicada!a!una!propiedad!de!un!
componente,! indica! que! esa! propiedad! es! de! entrada! de! datos,! es! decir,! cualquier!
propiedad! marcada! con! esta! directiva! podrá! recibir! el! valor! que! especifique! el!
componente!que!lo!llama.!
La! anotación!@Output,! por! el! contrario,! hace!que! la! propiedad!del!modelo! sea!
pública!para!el!resto!de!componentes.!!
Esta!última!directiva,!actúa!de!forma!parecida!a!los!eventos,!ya!que!estos!también!
se!exponen!al!resto!de!elementos.!Más!allá!de!los!eventos!predefinidos!que!proporciona!
! [UPM]!Máster*en*Ingeniería*Web!
Página!38!
Angular,! se! pueden! crear! eventos! propios! en! las! directivas! o! componentes! para!
completar!la!funcionalidad!de!la!aplicación.!
Esto! se! consigue! gracias! a! la! clase! EventEmitter.! Cuando! en! una! directiva! o!componente! se! crea! una! propiedad! del! tipo! EventEmitter,! se! consigue! que! esta!propiedad!sea!pública!(de!salida).!!
Se!llama!entonces!al!método!EventEmitter.emit(payload)!para!activar!un!evento,!pasando! un! mensaje! de! payload,! que! puede! ser! un! objeto! de! cualquier! tipo.! Los!elementos!que!estén!escuchando!el!evento!vinculado!a!esta!propiedad!podrán!acceder!
al!mensaje!de!payload!emitido!a!través!del!objeto!$event.!
2.3.4.! CICLO DE VIDA DEL COMPONENTE (LIFECYCLE
HOOK)
Los!componentes!y!directivas!Angular!tienen!una!serie!de!fases!que!van!desde!su!
creación,!hasta!su!destrucción,!pasando!por!la!detección!de!cambios.!El!framework!se!encarga!de!gestionar!estos!eventos,!que!en!su!conjunto!se!conocen!como!“ciclo!de!vida”!
de!los!componentes.!
Estos!ciclos,!son!las!herramientas!que!Angular!pone!a!disposición!del!programador!
para!para!obtener!un!mayor!control!de!la!aplicación,!permitiendo!ejecutar!código!en!un!
momento!concreto!del!ciclo!de!vida!del!componente.!
Se! implementan! a! través! de! una! serie! de! interfaces! contenidas! en! la! librería!
@angular/core.!Cada!una!de!estas!interfaces!expondrá!un!método!único,!que!la!clase!
del!componente!sobrescribirá!para!incluir!la!funcionalidad!necesaria!en!la!aplicación.!El!
nombre!de!estos!métodos!se!corresponden!con!el!nombre!de!su!interfaz!prefijado!con!
ngo.!
No! es! necesario! que! la! clase! implemente! todas! las! interfaces! del! ciclo! de! vida,!
Angular!solamente!llamará!a!aquellas! interfaces!cuyos!métodos!estén!definidos!en!el!
componente!o!directiva.!Es!más,!no!es!necesario!añadir!las!interfaces!a!estos!elementos.!
En!JavaScript!no!existen!las!interfaces,!por!lo!que!Angular!no!puede!ver!las!interfaces!de!
TypeScript!en!tiempo!de!ejecución!ya!que!desaparecen!en!la!transpilación!a!JavaScript.!!
Para!ejecutar!los!métodos!del!ciclo!de!vida,!Angular!inspecciona!las!clases!en!busca!
de!la!definición!de!los!métodos!cuya!nomenclatura!coincide!con!los!de!las!interfaces.!Sin!
embargo,! aunque! no! sea! necesario! incluir! la! implementación! de! la! interfaz,! se!
recomienda!hacerlo!por!el!beneficio!que!supone!en!el!tipado!fuerte!(Google,!Angular,!
2018).!
Después!de!la!llamada!al!constructor!para!crear!el!componente/directiva,!Angular!
llama!a!los!métodos!definidos!en!la!clase!del!ciclo!de!vida!en!el!orden!que!se!muestra!en!
la!Imagen!9!(Hussain,!2016).!!
! Comparativa*entre*Angular*y*AngularJS.*Evolución*a*Angular*5.!
Angela!Serrano!Sánchez!! ! Página!39!!
!Imagen*9.*Métodos*del*ciclo*de*vida*de*un*componente*Angular*
2.3.4.1.! NGONCHANGE
Pertenece!a!la!interfaz!OnChange.!Es!el!primer!método!en!llamarse,!incluso!antes!
de!ngOnInit()!y!se!ejecuta!cada!vez!que!una!o!varias!de!las!propiedades!de!entrada!del!
componente!han!cambiado.!Recibe!como!parámetro!un!objeto!del!tipo!SimpleChange,!que!encapsula!el!valor!actual!y! !anterior!de!la/s!propiedad/es!cambiada/s.!El!método!
itera!sobre!cada!propiedad!cambiada!y!las!registra.!!
2.3.4.2.! NGONINIT
Corresponde!a!la!interfaz!OnInit!y!es!invocado!solamente!una!vez!después!de!que!
Angular! ha! terminado! de! crear! e! inicializar! el! componente.! Es! decir,! es! llamado!
directamente! después! del! constructor! y! de! la! primera! ejecución! del! método!
ngOnChange.!
Se! usa! ngOnInit! principalmente! por! dos! motivos;! para! realizar! inicializaciones!
complejas!de!forma!rápida!después!de!su!construcción!y!para!configurar!el!componente!
después!de!que!Angular!establezca!las!propiedades!de!entrada.!
CONSTRUCTOR VS NGONINIT
Si!ngOnInit!sirve!para!inicializar!el!componente,!entonces!¿cómo!y!cuándo!se!debe!
utilizar!cada!elemento?!
Por!norma!general,!el!constructor!solamente!debe!encargarse!de!inicializaciones!
simples.! La! lógica! compleja! de! inicialización! debería! llevarse! a! cabo! en! el! método!
ngOnInit.!Si!hay!que!inicializar!el!componente!en!base!a!ciertas!propiedades!de!entrada,!
que!son!recuperadas!por!el!método,!entonces!ngOnInit!es!la!mejor!opción!para!realizar!
esta!inicialización.!!
! [UPM]!Máster*en*Ingeniería*Web!
Página!40!
2.3.4.3.! NGDOCHECK
El!método!ngDoCheck!pertenece!a!la!interfaz!DoCheck,!que!a!su!vez!extiende!de!la!
interfaz! OnChanges.! Se! recomienda! no! implementar! los! dos! métodos! en! el! mismo!
componente!ya!que,!al!heredar!DoCheck!de!la!clase!OnChanges,!ésta!queda!sobrescrita!
y!por!tanto,!ignorada.!
Este!método! detecta! y! actúa! sobre! los! cambios! que! Angular! no! captura! por! sí!
mismo.!Se!inspeccionan!ciertos!valores!de!interés,!capturando!y!comparando!su!estado!
actual!con!los!valores!anteriores.!
Si!está!definido!en!la!clase,!este!método!es!llamado!con!una!frecuencia!enorme,!
porque! que! se! ejecuta! después! de! cada! ciclo! de! detección! de! cambio,! sin! importar!
dónde!haya!ocurrido!el!cambio.!
El!simple!hecho!de!pasar!el!ratón!por!algún!<input>!de!la!página,!desencadena!una!
llamada.!Al!realizarse!tantas!llamadas!a!este!método,!la!implementación!debe!ser!lo!más!
ligera!posible!o!la!experiencia!del!usuario!podría!verse!afectada.!
2.3.4.4.! NGONDESTROY
Invocado!cuando!el!componente!es!destruido,!pertenece!a!la!interfaz!OnDestroy.!
Es!el!lugar!donde!se!deben!liberar!recursos!que!no!serán!recogidos!por!el!recolector!de!
basura!de!forma!automática.!Es!decir,!en!este!método!debe!incluirse!cualquier!línea!de!
código!que!limpie!las!referencias!que!permanezcan!en!las!variables!de!instancia,!y!donde!
se!deben!anular!la!suscripciones!a!los!elementos!observables!(ver!apartado!Observables!
&!RxJS),!así!como!separar!los!manejadores!de!eventos!para!evitar!pérdidas!de!memoria.!
También! debe! ser! en! este!método! donde! se! notifique! a! las! otras! partes! de! la!
aplicación!que!el!componente!ha!desaparecido.!
2.3.4.5.! NGAFTERCONTENT Y NGAFTERVIEW
Estos!métodos!se!aplican!a!los!componentes!hijos,!cuando!éstos!son!creados.!
Los!métodos!ngAfterView!actúan!cuando!los!valores!de!las!vistas!hijas!cambian,!que!
solo! pueden! ser! accedidas! a! través! de! las! propiedades! que! tengan! el! decorador!
@ViewChild!asociado.!Los!metadatos!de! la!anotación!anterior!hacen!referencia!a! los!
componentes! hijos,! cuyas! etiquetas! de! elemento! aparecen!dentro!de! la! plantilla! del!
componente!padre.!
ngAfterViewInit,! implementa! la! interfaz! AfterViewInit! y! se! lanza! después! de! la!
inicialización!de!la!vista!del!componente!y!de!las!vistas!hijas.!Es!llamado!una!única!vez!
tras!la!ejecución!de!la!primera!llamada!a!ngAfterContentChecked().!
ngAfterViewChecked,!corresponde!a!la!interfaz!AfterViewChecked!y!comprueba!el!
estado!de!la!vista!del!componente!padre!y!de!las!vistas!de!los!componente!hijos.!
! Comparativa*entre*Angular*y*AngularJS.*Evolución*a*Angular*5.!
Angela!Serrano!Sánchez!! ! Página!41!!
Los! métodos! ngAfterContento! son! similares! a! los! anteriores,! salvo! que! hacen!
referencia!a! los!componentes!hijo!que!Angular!proyecta5!en!el!componente!padre,!y!
cuyas!propiedades!son!accedidas!a!través!de!la!anotación!@ContentChild.!
ngAfterContentInit!se! lanza!después!de!que!Angular!proyecte!contenido!externo!
en! la!vista!del!componente.!Es! llamado!sólo!una!vez!después!del!primer!ngDoCheck.!
Pertenece!a!la!interfaz!AfterContentInit.!
Por! último,! ngAfterContentChecked,! es! llamado! después! de! que! Angular!
compruebe! el! contenido! externo! proyectado! en! el! componente.! Corresponde! a! la!
interfaz! AfterContentChecked! y! se! lanza! después! de! ngAfterContentInit,! y! tras! cada!
ngDoCheck.!
2.4.! DIRECTIVAS
Las! directivas! podrían! definirse! como! componentes! sin! vistas,! o! dicho! de! otro!
modo,!un!componente!podría!definirse!como!una!directiva!con!plantilla.!El!componente!
es!la!forma!más!común!de!directiva,!pero!también!existen!otros!tipos;!estructurales!y!
de!atributos,!que!son!las!que!se!contemplan!en!este!apartado,!ya!que!los!componentes!
han!sido!estudiados!en!detalle!en!el!apartado!anterior.!
2.4.1.! DIRECTIVAS ESTRUCTURALES
Este!tipo!de!directivas!se!encargan!de!manipular!el!diseño!del!DOM,!añadiendo,!
modificando!o!eliminando!elementos,! cambiando! la! estructura!de! la!plantilla!que! se!
muestra.!El!uso!de!este!tipo!de!directivas!se!justifica!por!el!rendimiento!y!productividad!
que! aportan! a! la! aplicación.! Al! manipular! los! elementos! del! DOM,! modificarlos! o!
eliminarlos!de!la!estructura!puede!suponer!modificar!o!eliminar!componentes!con!lógica!
pesada.!Si!el!componente!sigue!asociado!al!DOM,!su!comportamiento!se!mantiene,!es!
decir,!sigue!escuchando!eventos,!comprobando!cambios!en!las!propiedades,!etc.!Esto!
hace!que!el! componente,! aunque!no!esté!directamente!en!uso,! consuma! recursos! y!
repercuta!directamente!en!el!rendimiento!de!la!aplicación!y!el!consumo!de!memoria.!
Ya! que! estas! directivas! pueden! llevar! a! cabo! acciones! complejas! en! el!
comportamiento!del!DOM,!no!puede!aplicarse!más!de!una!directiva!estructural!a!la!vez!
sobre!el!mismo!elemento.!
Las!directivas!estructurales!son!fáciles!de!reconocer,!ya!que!su!nomenclatura!va!
precedida! por! un! asterisco! (*)! sin! corchetes! ni! paréntesis.! Esta! sintaxis,!
*nombreDirectiva,! se! denomina! “azúcar! sintáctico”! ya! que! Angular! es! capaz! de!
descomponer!esa!notación!en!algo!más!complejo,!que!es!la!sintaxis!real!de!la!directiva.!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!5!Forma!de!importar!contenido!HTML!desde!fuera!del!componente!e!insertar!ese!contenido!en!el!hueco!designado!dentro!de!la!plantilla!del!componente.!
! [UPM]!Máster*en*Ingeniería*Web!
Página!42!
Internamente!Angular!traduce!la!notación!*nombreDirectiva!de!la!directiva!en!un!
elemento!denominado!<ngotemplate>.!Este!elemento!renderiza!el!HTML!y!convierte!la!
directiva!en!un!elemento!de!tipo!property*binding;![nombreDirectiva]!
2.4.1.1.! DIRECTIVAS ESTRUCTURALES PREDEFINIDAS
Para!este!tipo!de!directivas!Angular!ya!proporciona!algunas!predefinidas,!que!son!
las!de!uso!más!común,!no!solo!en!Angular,!sino!en!todos!los!lenguajes!de!programación;!
las!estructuras!condicionales!if,!for!y!switch.!
Al!ser!directivas,!cada!una!está!declarada!en!sus!respectivas!clases!NgIf,!NgForOf!y!
NgSwitch.!
NGIF
La!directiva!*ngIf!aplicada!a!un!elemento!HTML!de!la!plantilla,!muestra!o!elimina!
su! contenido!en! función!del! valor!devuelto!por! la!expresión!evaluada.!Es!decir,! si! se!
cumple!la!condición!evaluada,!el!contenido!del!elemento!se!añade!al!DOM,!y!si!no,!lo!
elimina.!Esta!directiva!se!aplica!sobre!el!elemento!en!cuestión!y!sobre!todos!sus!hijos.!
En! función!de! lo!mencionado!anteriormente!Angular! traducirá!una!sentencia!de!
tipo!*ngIf!como!la!siguiente;!
<div *ngIf="object" class="name">{{object.name}}</div>
En!su!equivalente!<ngotemplate>;!
<ng-template [ngIf]="object"> <div class="name">{{object.name}}</div> </ng-template>
NGFOROF
Sirve!para!procesar!elementos!de!un!objeto!iterable,!creando!por!cada!uno!de!ellos!
un!elemento!en!el!DOM.!La!directiva!es!*ngFor!y!es!la!encargada!de!guiar!el!proceso!de!
repetición.!!
Su! sintaxis! es! *ngFor="let! value! of! values",! donde! values! es! la! propiedad! del!componente! a! iterar! y! value! es! una! variable! local! donde! se! almacena! el! valor! del!
elemento! values! iterado.! La! expresión! asignada! a! la! directiva! *ngFor,! no! es! una!expresión!de!plantilla! como!en!el! caso!de!*ngIf,! sino! lo!que! se!denomina! como!una!
microsintaxis;!un!pequeño!lenguaje!por!si!mismo!que!Angular!es!capaz!de!interpretar,!y!
que!permite!configurar!una!directiva!como!un!string!de!forma!compacta!y!amigable.!
Se!considera!en!el!siguiente!ejemplo! la!transformación!que! lleva!Angular!a!cabo!
sobre!la!directiva!de!*ngFor!a!<ngotemplate>.!
<div *ngFor="let value of values; let i=index; trackBy: trackById" [class.odd]="odd">
! Comparativa*entre*Angular*y*AngularJS.*Evolución*a*Angular*5.!
Angela!Serrano!Sánchez!! ! Página!43!!
({{i}}) {{value.name}} </div>
!
<ng-template ngFor let-value [ngForOf]="values" let-i="index" [ngForTrackBy]="trackById"> <div [class.odd]="odd">({{i}}) {{value.name}}</div> </ng-template>
!
El! lenguaje!de!microsintaxis!se!encarga,!por!ejemplo,!de!convertir! la!parte!de! la!
sentencia! let* value! de! la! primera! sintaxis,! en! la! variable! de! entrada! letovalue! en! la!
transformación! a! su! equivalente! <ngotemplate>.! Esta! variable! será! referenciada!
únicamente!en!el!contexto!de!la!plantilla.!También!es!responsable!de!prefijar!con!ngFor!
los! elementos! of! y! trackBy,! convirtiéndolos! en! ngForOf! y! ngForTrackBy,! que! se!
corresponden!con!propiedades!de!entrada!de!la!directiva!NgFor.!!
En! este! ejemplo! ngForOf! indica! la! propiedad! sobre! la! que! se! debe! iterar! y!
ngForTrackBy!la!función!que!llevará!un!registro!de!los!cambios.!
En!el!ejemplo!la!primera!sentencia!también!contiene!let! i=index,!que!muestra!el!
uso! de! la! propiedad! index! de!Angular! en! el! contexto! de! la! directiva.! Esta! propiedad!siempre!comienza!en!cero,!y!se!incrementa!en!cada!iteración.!
NGSWITCH
NgSwitch! funciona! como! la! instrucción! switch! de! JavaScript,! puede!mostrar! un!
elemento!concreto!de!un!conjunto!de!elementos,!en!función!de!una!condición.!Angular!
solo!pondrá!en!el!DOM!el!elemento!seleccionado.!
Esta!instrucción!es!diferente!a!las!anteriores,!ya!que!NgSwitch!se!compone!de!tres!
directivas!que!cooperan!entre!sí;!NgSwitch,!NgSwitchCase!y!NgSwitchDefault.!NgSwitch!
es!la!directiva!controladora!que!evalúa!la!condición!de!la!expresión!y!retorna!el!valor!
por!el!que!se!guiará!el!switch.!
Hay!una!particularidad!en!estos!elementos,!y!es!que!NgSwitch!no!es!una!directiva!
estructural,!sino!una!directiva!de!atributo,!ya!que!es! la!que!se!encarga!de!cambiar!el!
comportamiento!de!las!otras!dos,!pero!no!modifica!el!DOM!directamente.!Las!otras!dos!
sí! que! son! directivas! estructurales;! modificarán! el! DOM! mostrando! el! elemento!
resultante!y!eliminando!el!resto!(Nate!Murray,!2018).!
*ngSwitchCase!añade!el!elemento!al!DOM!cuando!el!valor!asociado!coincide!con!el!
devuelto!por!la!expresión!evaluada!del!NgSwitch.!Cuando!dicho!valor!no!se!encuentra!
en!ninguna!de!las!condiciones!del!case,!se!muestra!en!el!DOM!un!elemento!por!defecto!
que!viene!definido!por!la!directiva!*ngSwitchDefault.!
! [UPM]!Máster*en*Ingeniería*Web!
Página!44!
2.4.1.2.! DIRECTIVAS ESTRUCTURALES PERSONALIZADAS
Si! por! algún! motivo,! la! funcionalidad! de! la! aplicación! requiere! modificar! el!
comportamiento! del! DOM! y! ninguna! de! las! directivas! predefinidas! se! ajusta! a! la!
funcionalidad!necesitada,!Angular!permite!crear!directivas!personalizadas.!
Una!directiva!se!crea!de!forma!similar!a!un!componente,!pero!utiliza!el!decorador!
@Directive!en!la!clase!en!lugar!de!@Component.!A!la!propiedad!selector!de!la!anotación!@Directive!se!le!debe!asignar!un!nombre,!que!será!el!que!identifique!la!directiva!cuando!
se!aplique!en!las!plantillas.!!
Como! requisito! imprescindible! para! el! desarrollo! de! cualquier! directiva,! deben!
importarse!las!clases!Input,!TempleteRef!y!ViewContainer!de!@angular/core.!
Cuando! se! crea! una! directiva! estructural,! se! crea! una! vista! embebida! por! el!
elemento!<ngotemplate>!e! inserta!esa!vista!en!un!contenedor!de!vistas!adyacente!al!
elemento! HTML! original! donde! se! aplica.! Para! recoger! el! contenido! tanto! del! <ngo
template>,!como!del!contenedor!de!la!vista!se!utilizan!TemplateRef!y!ViewContainerRef!
respectivamente.!Las!dependencias!de!estos!elementos!se!inyectan!en!el!constructor!de!
la!directiva.!!
Por!último!a!la!directiva!habrá!que!asignarle!un!comportamiento,!en!función!de!lo!
que! se! espere!de! ella! por! lo! que! las! propiedades!que! se! definan!deberán!poder! ser!
accedidas,!esto!se!consigue!aplicando!la!directiva!@Input.!!
2.4.2.! DIRECTIVAS DE ATRIBUTOS
Las! directivas! de! atributo! “escuchan”! y! modifican! el! comportamiento! de! otros!
elementos,!atributos,!propiedades!y!componentes!de!HTML.!Por!lo!general,!se!aplican!
como! si! fueran! atributos! de! HTML,! es! decir,! sólo! modifican! la! apariencia! de! los!
elementos!de!la!plantilla,!de!ahí!el!nombre.!
2.4.2.1.! DIRECTIVAS DE ATRIBUTOS PREDEFINIDAS
Al! igual! que! para! las! directivas! estructurales,! Angular! ya! proporciona! algunas!
directivas!de!este!tipo,!predefinidas!en!el!framework.!
NGCLASS
Por! norma! general! la! apariencia! de! los! elementos! se! controla! añadiendo! o!
eliminando! clases!CSS!dinámicamente.! Para!modificar! varias! clases! simultáneamente!
puede!utilizarse!NgClass.!Su!sintaxis!es!la!siguiente;!
<div [ngClass]="setClasses">
!
! Comparativa*entre*Angular*y*AngularJS.*Evolución*a*Angular*5.!
Angela!Serrano!Sánchez!! ! Página!45!!
Donde! “setClasses”! es! la! expresión! que! se! evalúa! y! por! la! que,! en! función! del!
resultado!que!devuelva,!la!clase!o!clases!serán!añadida!o!no!al!elemento!objetivo!del!
DOM.!
NGSTYLE
Esta! directiva! permite!modificar! las! propiedades! de! estilo! de! los! elementos! del!
DOM.!Su! funcionamiento!es!similar!al!de!Style*Binding,! visto!en!el!apartado!de!Data*Binding.! La! diferencia! radica! en! que,! style* binding! sólo! permite! modificar! las!
propiedades!de!un!único!estilo,!y!la!directiva!ngStyle,!permite!modificar!múltiples!estilos!
de!un!elemento!al!mismo!tiempo.!!
Su!sintaxis!es!similar!a!la!de!la!directiva!anterior;!
<div [ngStyle]="setStyles" >
!!
Aunque!se!pueden!definir!las!propiedades!directamente!en!la!etiqueta!HTML!del!
DOM!a!modificar;!
[ngStyle]="{'color': 'blue', 'font-size': '24px', 'font-weight': 'bold'}"
NGMODEL
El!caso!de!la!directiva!ngModel,!es!particular,!y!difiere!de!las!dos!anteriores!en!que!
utiliza!la!técnica!del!twoFway*data*binding!en!vez!de!la!de!property*binding.!Se!utiliza!principalmente!en!elementos!de!formularios,!donde!no!solo!es!necesario!
mostrar!información!al!usuario,!sino!permitirle!modificar!esa!información,!es!decir,!el!
usuario!puede!modificar!las!propiedades!de!los!componentes!de!la!aplicación.!
Utilizar! [(ngModel)]! equivale! a! utilizar! las! técnicas! de! property* binding! e! event*binding!sobre!el!mismo!elemento!de!un!formulario.!La!sintaxis!de!esta!directiva;!
<input [(ngModel)]="currentObject.name">
!
Podría!desglosarse!en;!!
<input [ngModel]="currentObject.name" (ngModelChange)="currentObject.name=$event">
!
Esta!directiva!asigna!un!valor!a!la!propiedad!del!elemento!y!además!“escucha”!los!
cambios!en!el!valor!de!dicha!propiedad.!Estos!detalles!son!específicos!para!cada!tipo!de!
elemento!y!por!lo!tanto,!la!directiva!NgModel!solo!funciona!para!elementos!admitidos!
! [UPM]!Máster*en*Ingeniería*Web!
Página!46!
por!la!interfaz!de!ControlValueAccessor6.!Angular!proporciona!este!acceso!en!todos!los!
elementos!básicos!de!formularios,!por!ello!su!uso!requiere!que!se!importe!el!módulo!
FormsModule!en!la!lista!de!imports!de!NgModel,!como!se!verá!más!adelante.!
2.4.2.2.! DIRECTIVAS DE ATRIBUTOS PERSONALIZADAS
Para!crear!una!directiva!de!atributo!personalizada,!debe!hacerse!con!el!decorador!
@Directive,!como!ya!se!vio!en!el!caso!de!las!directivas!estructurales.!En!el!caso!de!este!
último! tipo! de! directivas! se! vio! que,! para! crear! una! directiva! personalizada! debían!
importarse! e! inyectarse! en! el! constructor! unas! clases! específicas! que! permiten!
manipular!los!elementos!del!DOM.!
En!el!caso!de!las!directivas!de!atributos!va!a!ocurrir!lo!mismo,!va!a!ser!necesario!
importar! e! inyectar! la! clase! ElementRef! que! da! acceso! directo! a! los! elementos!
contenedores,! a! través! de! la! propiedad! nativeElement! y! la! clase! Renderer! que!
proporciona!métodos!auxiliares!para!modificar!los!elementos!del!DOM.!
Una! directiva! creada! utilizando! únicamente! esta! clase! sólo! aplicará! el!
funcionamiento!a!un!elemento!específico,!pero!no!permitirá!al!usuario!realizar!ninguna!
acción! sobre! el! elemento.! Para! conseguir! que! la! directiva! funcione! de!manera!más!
dinámica,!se!importa!e!inyecta!la!clase!HostListener.!Mediante!esta!clase!y!el!uso!de!la!
anotación!@HostListener,!Angular!permite!vincular!un!método!de! la!directiva!con!un!
evento!del!elemento!contenedor!en!el!DOM.!
Del!mismo!modo!que!con!los!eventos,!se!puede!querer!modificar!una!propiedad!
del!elemento!vinculado!a!la!directiva.!Como!ya!se!ha!mencionado!esto!puede!hacerse!
utilizando!ElementRef,!pero!se!pierde!el!dinamismo!que!necesita!la!directiva,!para!estos!
casos! se! utiliza! la! anotación!@HostBinding.! Utilizando! este! decorador! una! directiva!
puede! vincular! una! propiedad! interna! a! una! propiedad! de! entrada! del! elemento!
contenedor,! de!modo! que! si! la! propiedad! interna! cambia,! la! propiedad! de! entrada!
cambiará!también.!
2.5.! FILTROS
Del!mismo!modo!que!el!resto!de!elementos!en!Angular,!las!pipes!o!filtros!son!clases!con! una! funcionalidad! concreta,! definida! por! los! metadatos! de! la! anotación!@Pipe!
asociada!a!la!clase.!
En!concreto,!los!filtros!en!Angular!sirven!para!transformar!o!convertir!valores!de!
datos! en! el! formato! requerido! dentro! de! la! plantilla! HTML,!más! concretamente,! se!
aplican!a!un!dato!y!se!evalúan!en!la!expresión!definida.!!
Su!sintaxis!es!<span>!{{!data!|!pipe!:!<parameters>!}}!</span>!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!6!Interfaz!de!Angular!que!hace!de!puente!entre!la!API!de!Angular!forms!y!los!elementos!del!DOM.!
! Comparativa*entre*Angular*y*AngularJS.*Evolución*a*Angular*5.!
Angela!Serrano!Sánchez!! ! Página!47!!
Los!parámetros!del!filtro,!pueden!son!opcionales!y!se!indican!para!definir!el!formato!
concreto!que!debe!aplicarse!a!la!transformación!de!los!datos.!
2.5.1.! FILTROS PREDEFINIDOS
Hay! tipos! de!datos,! que!por! convención!o! por! localización,! suelen!necesitar! ser!
transformados!más!comúnmente,!como!por!ejemplo!las!fechas!o!las!monedas.!Angular!
provee!al!framework!de!una!serie!de!filtros!disponibles!para!utilizar!directamente!en!las!
plantillas.!
Algunos! ejemplos! de! estos! filtros! son:! CurrencyPipe,* DatePipe,* DecimalPipe* ,*JsonPipe,*LowerCasePipe,*PercentPipe,*SlicePipe,*TitleCasePipe,*UpperCasePipe!y!la!más!
interesante,!AsyncPipe!que!se!verá!en!detalle!en!el!apartado!Observables!en!Angular!con!RxJS.!
2.5.2.! FILTROS PERSONALIZADOS
Para!poder!crear!un!filtro!personalizado,!además!de!utilizar! la!anotación!@Pipe,!
como!se!indicaba!al!comienzo!de!este!apartado,!es!necesario!que!la!clase!implemente!
la! interfaz!PipeTransform!y!sobrescriba!el!método!transform.!Este!método!acepta!un!
valor!de!entrada!y!una!serie!de!parámetros!opcionales!y!devuelve!el!valor!transformado.!
Además!en! los!metadatos!del!decorador!@Pipe! se! indicará!el! nombre!que!va!a!
recibir!el!filtro.!Utilizando!el!nombre!que!se!ha!definido!en!la!anotación,!el!filtro!podrá!
utilizarse!en!las!plantillas!HTML,!del!mismo!modo!que!el!resto!de!pipes.!!Teniendo!en!cuenta!estas!pautas!la!implementación!de!un!filtro!resulta!bastante!
sencilla.!
2.5.3.! FILTROS PUROS E IMPUROS
Por!defecto!en!Angular!todos!los!filtros!son!puros,!tanto!los!predefinidos!como!los!
personalizados.! Esto! quiere! decir! que! el! filtro! sólo! se! ejecuta! cuando! se! detecta! un!
cambio!en!un!valor!de!entrada!primitivo!(String,*Number,*Boolean)!o!una!referencia!de!objeto!modificada!(Objeto,!Array),!pero!se!ignoran!los!cambios!producidos!dentro!del!
objeto.!
Esto!se!debe!principalmente!al!rendimiento,!una!comprobación!de!referencia!de!
objeto!es!mucho!más!rápida!que!una!comprobación!exhaustiva!en!una!propiedad!del!
objeto!para!encontrar!la!diferencia.!
Este!comportamiento!está!deshabilitado!por!defecto,!pero!si!fuese!necesario!que!
un! filtro! aplicase! este! tipo! de! comportamiento,! podría! establecerse! en! el! decorador!
@Pipe,!la!propiedad!pure!a!false.!El!filtro!se!ejecutará!entonces!en!cada!ciclo!detección!de!cambios!del!componente,!
lo! que! puede! provocar! ralentizar! el! funcionamiento! de! la! aplicación! y! afectar!
negativamente!al!rendimiento!de!ésta!si!se!implementan!este!tipo!de!filtros.!
! [UPM]!Máster*en*Ingeniería*Web!
Página!48!
2.6.! SERVICIOS E INYECCIÓN DE DEPENDENCIAS
Como! ya! se! vio! en! el! apartado! de! arquitectura! de! Angular,! la! inyección! de!
dependencias!es!una!de!las!piedras!angulares!del!framework.!El!patrón!de!inyección!de!dependencias,!es!un!patrón!de!diseño!orientado!a!objetos!
en!el!que!una!clase!recibe!las!dependencias!desde!otras!clases,!en!vez!de!crearlas.!La!
idea!de!mover!la!responsabilidad!de!crear!una!instancia!concreta!de!una!dependencia!a!
otro! sitio! fuera! de! la! clase,! se! denomina! Inversión! de! Control! (IoC,! en! sus! siglas! en!
Inglés),! técnica! en! la! que! se! basa! la! implementación! del! patrón! de! inyección! de!
dependencias.!
El! uso! de! este! patrón! permite! desacoplar! los! distintos! componentes! de! una!
aplicación,!ya!que!la!modificación!de!una!clase!que!es! inyectada,!no!repercute!en!las!
clases!que!reciben!su!dependencia.!Es!posible!reducir!e!incluso!eliminar!dependencias!
innecesarias!en!los!componentes,!haciendo!que!el!éste!sea!reusable!en!otros!contextos.!
El!código!se!vuelve!entonces,!más!limpio!y!más!fácil!de!leer!y!mantener.!
2.6.1.! INYECCIÓN DE DEPENDENCIAS EN ANGULAR
Angular! hace! uso! de! este! patrón! e! implementa! su! propia! inyección! de!
dependencias! en! el! framework.! Este! ! patrón! se! usa! en! Angular! principalmente! para!
inyectar! en! los! componentes! instancias! de! servicios,! que! son! las! clases! que! aportan!
funcionalidad!transversal!a!la!aplicación.!!
La! estructura! de! Angular! establece! que! los! componentes! deben! dedicarse! a!
presentar!la!información!y!delegar!el!acceso!a!los!datos!a!los!servicios.!Los!servicios!son!
una!buena!forma!de!compartir!información!entre!clases!que!no!se!conocen!entre!sí.!Su!
función!principal!es!interactuar!con!la!base!de!datos,!acceder!a!la!lógica!de!negocio!!y!
comunicar!componentes!y!clases!de!la!aplicación.!
Un! servicio,! no! es! más! que! una! clase! normal,! a! la! que! se! le! añaden! algunos!
elementos! particulares! para! que! pueda! inyectarse! y! utilizarse! en! el! resto! de!
componentes!de!la!aplicación.!!
Estos! elementos! componen! la! inyección! de! dependencias! de! Angular! y! son! los!
siguientes;!
•! el!proveedor!mapea!un!token!(identificador!de!la!dependencia!registrada)!en!una! lista!de!dependencias,!que! luego!le!dice!a!Angular!cómo!crear!un!
objeto,!dado!ese!token.!•! el! inyector! es! responsable! de! resolver! las! dependencias! e! inyectarlas! al!
crear!objetos.!
•! la!dependencia!es!la!instancia!de!la!clase!que!se!está!inyectando.!
!
! Comparativa*entre*Angular*y*AngularJS.*Evolución*a*Angular*5.!
Angela!Serrano!Sánchez!! ! Página!49!!
!Imagen*10.*Esquema*de*inyección*de*dependencias*en*Angular*
2.6.1.1.! INYECTORES!
En! su! implementación! de! inyección! de! dependencias,! Angular! proporciona!
inyectores!que!son!los!responsables!de!crear!las!instancias!de!los!servicios!e!inyectarlas!
en!las!clases!o!componentes!correspondientes.!
Angular! abstrae! al! desarrollador! de! implementar! estos! inyectores,! ya! que! el!
framework!los!crea!durante!la!ejecución!de!la!aplicación,!comenzando!por!el!inyector!
raíz!declarado!durante!el!proceso!de!bootstrapping.!!Lo!que!Angular!no!sabe!es!cómo!crear!instancias!de!los!servicios!o!el!inyector!para!
crear!el!servicio,!eso!debe!configurarse!manualmente!especificando!los!proveedores!de!
cada! servicio.! Para! ello! puede! utilizarse! el! propio! inyector,! como! se! detalla! a!
continuación.!
PROVEEDORES EN @INJECTABLE
Este!decorador!identifica!los!servicios!y!clases!que!van!a!ser!inyectados!y!utilizados!
en! otras! partes! de! la! aplicación,! pero! también! puede! utilizarse! para! configurar! los!
proveedores!de!esos!servicios.!Por!defecto!el!CLI!de!Angular!configura!los!proveedores,!
indicando!al!framework!que!el!inyector!raíz!es!el!responsable!de!crear!una!instancia!del!servicio.!
@Injectable({ providedIn: 'root', })
!
Pero!a!veces!conviene!reducir!el!uso!del!servicio,!o!que!se!provea!dicho!servicio!en!
un!contexto!de!carga!lenta!(lazyFload*context),!para!no!realizar!una!carga!del!servicio!hasta!que!éste! sea! invocado!por! la! aplicación.! En!este! caso!el!proveedor!debe!estar!
asociado!a!una! clase!@NgModule!específica,! y! ser!usado!por! cualquier! inyector!que!
incluya!ese!módulo.!
! [UPM]!Máster*en*Ingeniería*Web!
Página!50!
PROVEEDORES EN @NGMODULE
Para!indicar!a!Angular!que!un!servicio!puede!ser!inyectado!en!todas!las!clases!que!
se! creen! en! un! módulo! concreto,! se! debe! registrar! el! proveedor! en! el! array! de!
proveedores!del!decorador!@NgModule!correspondiente.!
Una! vez! creada! la! instancia!del! servicio,! ésta! vive!durante!el! ciclo!de! vida!de! la!
aplicación!y!Angular!inyecta!esta!instancia!única!en!cada!clase!que!lo!necesite.!
PROVEEDORES EN @COMPONENT
Si! los! proveedores! se! declaran! en! el! array! de! proveedores! específico! de! un!
componente,! el! servicio! inyectado! sólo! podrá! ser! utilizado! por! ese! componente! en!
concreto,!o!por!sus!componentes!hijos.!
El!servicio!proporcionado!en!un!componente!puede!tener!una!vida!imitada.!Una!
instancia!del!servicio!será!creada!cada!vez!que!se!cree!una!instancia!del!componente!y,!
cuando!esta!última!se!destruye,!también!lo!hace!la!instancia!del!servicio.!
La!decisión!de!usar! la!declaración!de!un!proveedor!en! los!elementos!anteriores,!
dependerá! del! desarrollador! atendiendo! a! las! necesidades! de! funcionalidad! y!
rendimiento!de!la!aplicación.!!
2.6.1.2.! PROVEEDORES
Los!proveedores! le!dicen!al! inyector!cómo!crear!el!servicio.!Sin!un!proveedor,!el!
inyector!no!sabría!que!es!responsable!de!inyectar!el!servicio!y!tampoco!podría!crearlo,!
es!decir,!el!inyector!depende!de!los!proveedores!para!crear!instancias!de!los!servicios!
que!el!inyector!inyecta!en!componentes,!directivas,!pipes!y!otros!servicios.!Un!proveedor!es!básicamente!una! fuente!de! información!sobre!cómo!crear!una!
instancia!de!un!objeto.!Cuando!se!registra!un!proveedor,!se!asocia!un!token!de!inyección!de! dependencia! a! ese! proveedor,! que! es! el! identificador! del! objeto! que! puede! ser!
creado.!El!inyector!mantiene!un!mapa!interno!de!proveedores!al!que!referencia!cuando!
se!le!solicita!una!dependencia.!El!token!es!la!clave!del!mapa.!
Hay! tres! tipos! de! proveedores:! proveedores! de! clase,! proveedores! factory! y!proveedores!de!valor.!!
PROVEEDORES DE CLASE
La! forma! más! común! de! encontrar! referenciados! los! proveedores! es! con! los!
proveedores!de!clase.!Cuando!se!crea!un!servicio,!dicho!servicio!recibe!un!nombre!de!
clase.! Precisamente! a! este! nombre! de! clase! será! al! que! vaya! asociado! el! decorador!
@Injectable!para!indicar!que!el!servicio!podrá!ser!inyectado!en!otros!elementos!de!la!
aplicación.!
A!la!hora!indicar!el!uso!de!este!servicio!en!los!providers,!tanto!de!la!anotación,!como!
del!módulo!o!del!componente,!podrá!hacerse!directamente!utilizando!el!nombre!de!su!
clase.!
Indicar!el!proveedor!como!el!nombre!de!la!clase;!!
! Comparativa*entre*Angular*y*AngularJS.*Evolución*a*Angular*5.!
Angela!Serrano!Sánchez!! ! Página!51!!
providers: [Clase]
!
Es!una!forma!reducida!de!la!expresión!real!para!declarar!un!proveedor;!!
providers: [{ provide: Clase, useClass: Clase }]
!
Dónde! la!propiedad!provide! contiene!el!nombre!del! token!que!sirve!como!clave!
para! localizar! la!dependencia!y! registrar!el!proveedor,! y!useClass! es! la!definición!del!objeto!proveedor.!
De! este! modo,! utilizando! la! expresión! anterior,! podría! asociarse! el! token! del!proveedor!a!una!definición!distinta!proporcionada!por!otra!clase;!
providers: [{ provide: Clase, useClass: OtraClase }]
PROVEEDORES DE VALOR
Este!tipo!de!proveedor!se!utiliza!cuando!no!es!necesario!crear!la!instancia!de!una!
clase,!sino!simplemente!utilizar!una!propiedad!concreta!de!algún!tipo!de!objeto.!En!vez!
de! inyectar!el! servicio! completo!en!otro!elemento,! como!ocurre!en!el! caso!anterior,!
habría!que!indicar!al!constructor!o!método!que!reciba!esta!dependencia!una!propiedad!
concreta!y!que!ésta!es!de!tipo!@Inject.!
constructor(@ Inject(‘provideProperty’) property: string)
PROVEEDORES DE FACTORÍA
A!veces!se!necesita!crear!dinámicamente!el!valor!dependiente,!en!función!de!una!
información!que!se!no!tendrá!hasta!el!último!momento!posible.!Tal!vez!la!información!
cambia! repetidamente! en! el! transcurso! de! la! sesión! del! navegador.! O! podría! darse!
también!que!el!servicio! inyectable!no!tiene!acceso!independiente!a! la!fuente!de!esta!
información.!
Esta!situación!requiere!un!proveedor!de!factoría.!
export let serviceProvider = { provide: ClassService, useFactory: classServiceFactory, deps: [dependentService] };
!
La! propiedad! useFactory! indica! a! Angular! que! el! proveedor! es! una! función! de!factoría!cuya!implementación!está!en!la!clase!classServiceFactory.!La!propiedad!deps!es!
un!array!de!tokens.!La!clase!dependentService!sirve!de!token!a!sus!propios!proveedores.!
! [UPM]!Máster*en*Ingeniería*Web!
Página!52!
El! inyector! resuelve! esos! tokens! e! inyecta! los! servicios! correspondientes! en! los!parámetros!de!la!función!de!factoría.!
2.6.1.3.! INYECCIÓN DE SERVICIOS
Aunque!en!este!punto!ya!se!ha!hecho!referencia!a!qué!es!un!servicio!y!qué!significa!
que! pueda! proveerse! e! inyectarse! en! otros! elementos,! falta! ver! cómo! se! realiza!
exactamente! este! proceso! en! la! implementación! del! componente,! directiva,! pipe! e!incluso!otros!servicios.!
La!inyección!en!Angular!se!realiza!inyectando!el!servicio!a!través!del!constructor!del!
elemento!en!el!que!se!quiere!utilizar!la!funcionalidad!de!dicho!servicio.!Por!ejemplo!la!
inyección!del!servicio!en!un!componente!quedaría!de!la!siguiente!manera;!
export class Component { property: any constructor(service: Service) { this.property = service.getServiceMethod(); } }
!
Donde!getServiceMethod() estaría!implementado!en!la!clase!del!servicio.!!
La! instancia!que!se!crea!es!de! tipo!singleton!dentro!del!alcance!del! inyector,!es!decir,!sólo!habrá!una!instancia!como!máximo!del!servicio!en!el!inyector.!
2.6.2.! JERARQUÍA DE INYECTORES
Angular!consta!de!un!sistema!de!inyección!de!dependencia!jerárquico.!Partiendo!
de! la! base! de! que! una! aplicación! angular! es! un! árbol! de! componentes,! y! que! cada!
instancia! de! componente! tiene! su! propio! inyector,! Angular! proporciona! un! árbol! de!
inyectores!paralelo!al!árbol!de!componentes.!Estos!inyectores!pueden!reconfigurarse!en!
cualquier!nivel!de!este!último!árbol.!
La!existencia!del!árbol!de!inyectores!supone!que,!cuando!un!componente!solicita!
una! dependencia,! Angular! intenta! satisfacer! esa! dependencia! con! un! proveedor!
registrado!en!el!inyector!del!componente.!Si!el!inyector!carece!del!proveedor,!transfiere!
la! solicitud! al! inyector! del! componente! superior.! Si! ese! inyector! tampoco! puede!
proporcionar! la!dependencia!solicitada,! la!solicitud!sigue!escalando!hacia!arriba!en!el!
árbol! de! inyectores! hasta! que,! o! bien! encuentra! un! inyector! que! puede!manejar! la!
solicitud,!o!se!queda!sin!nodos!de!búsqueda,!en!cuyo!caso!Angular!mostraría!un!error.!
Con! este! sistema,! no! es! necesario! registrar! el! mismo! servicio! en! diferentes!
inyectores,!y!de!hecho!en!la!documentación!oficial!de!Angular!se!recomienda!no!hacerlo,!
ya! que! al! escalar! la! petición! hacia! arriba,! algún! inyector! podrá! resolver! la! petición.!
Registrar! el! mismo! servicio! en! diferentes! inyectores! puede! suponer! problemas! de!
! Comparativa*entre*Angular*y*AngularJS.*Evolución*a*Angular*5.!
Angela!Serrano!Sánchez!! ! Página!53!!
rendimiento!y!de!seguridad!en!la!aplicación,!ya!que!cada!componente!que!inyecte!el!
servicio! tendrá! una! instancia! única! y! diferente! a! la! del! resto! de! componentes! que!
también!lo!inyecten.!!
2.6.3.! SERVICIOS DE ANGULAR
El! framework! de!Angular!proporciona!algunos! servicios!predefinidos!disponibles!para!utilizar!en!cualquier!elemento!de!la!aplicación.!!
La!siguiente!tabla!muestra! los!servicios!más!comúnmente!utilizados!a! la!hora!de!
desarrollar!una!aplicación!en!Angular.!
•! Http!! ! o>!Para!comunicaciones!http!con!el!servidor!•! Form!! ! o>!Para!manejar!el!código!asociado!a!los!formularios!•! Router!! o>!Para!realizar!la!navegación!de!la!aplicación!•! Animation!! o>!Para!mostrar!animaciones!en!la!interfaz!de!usuario!
Cada!uno!de!los!servicios!anteriores!están!contenidos!en!una!librería!específica!de!
Angular,!algunas!de!ellas!se!mencionan!en!los!siguientes!apartados!de!este!informe.!
2.7.! RXJS Y ANGULAR
Angular! hace! uso! de! un! paradigma! de! programación! denominado! reactive*programming,!a!través!del!uso!de!la!librería!RxJS!(Reactive*Extension*for*JavaScript),!que!proporciona!implementación!de!Observables!para!JavaScript.!
Aunque!no!es!necesario!tener!conocimientos!previos!de!programación!reactiva!o!
RxJS!para!desarrollar!aplicaciones!con!Angular,!puede!ser!conveniente!estudiarlo!para!
construir!una!mejor!arquitectura!de!la!aplicación.!!
El!estudio!de! la!programación!reactiva!queda!fuera!del!alcance!de!este! informe,!
aunque!en!los!siguientes!apartados!se!tratarán!los!conceptos!básicos!que!son!de!utilidad!
para!conocer!y!comprender!las!bases!del!funcionamiento!de!Angular!con!esta!técnica.!
2.7.1.! REACTIVE PROGRAMMING
La!programación!reactiva!es!un!paradigma!de!programación!asíncrono!relacionado!
con!flujos!de!datos!(también!denominados!streams,!secuencias!de!valores!en!el!tiempo)!
y! la!propagación!del! cambio,!es!decir,! la!programación! reactiva!es! la! idea!de!que! se!
puede! crear! todo! un! programa! simplemente! definiendo! los! diferentes! flujos! y! las!
operaciones!que!se!realizan!en!esas!secuencias.!Con!este!paradigma!se!define!cómo!se!
conecta!la!aplicación!y!cómo!se!introducen!los!valores,!de!forma!que!el!flujo!de!los!datos!
y!las!operaciones!se!encarguen!del!resto.!
! [UPM]!Máster*en*Ingeniería*Web!
Página!54!
2.7.2.! OBSERVABLES & RXJS
Los! observables! son! un! nuevo! tipo! primitivo! en! la! programación! reactiva,! que!
actúan! como! un! modelo! de! creación! de! secuencias,! de! cómo! suscribirse! a! ellas,!
reaccionar!a!los!nuevos!valores!y!combinar!secuencias!para!construir!otras!nuevas.!
Los!observables!proporcionan!soporte!para!pasar!mensajes!entre!publicadores!y!
suscriptores!en!la!aplicación!y!ofrecen!ventajas!significativas!sobre!otras!técnicas!para!
el!manejo!de!eventos,!programación!asíncrona!y!manejo!de!valores!múltiples.!
Los!observables!son!declarativos;!es!decir,!definen!funciones!que!publican!valores,!
pero! no! se! ejecutan! hasta! que! un! consumidor! se! suscribe.! El! consumidor! suscrito!
empieza!entonces!a!recibir!notificaciones,!hasta!que!la!función!finaliza,!o!hasta!que!se!
cancela!la!suscripción.!
Un! observable! puede! entregar! múltiples! valores! de! cualquier! tipo:! literales,!
mensajes! o! eventos,! según! el! contexto.! Debido! a! que! la! lógica! de! configuración! y!
extracción! es! manejada! por! el! observable,! el! código! desarrollado! solo! necesita!
preocuparse! de! suscribirse! para! consumir! valores! y! cuando! termine,! cancelar! la!
suscripción.!Debido!a!estas!ventajas,!los!observables!se!usan!ampliamente!en!Angular,!
y!también!se!recomiendan!para!el!desarrollo!de!aplicaciones.!
La!librería!que!contiene!la!implementación!de!los!observables!para!JavaScript!y!que!
es!también!la!que!utiliza!Angular!es!RxJS.!Es!una!biblioteca!de!programación!reactiva!
que!hace!que!sea!más!fácil!componer!código!asíncrono!o!de!devolución!de!llamadas.!!
La! librería!RxJS!dispone!de!una!serie!de!operadores!o!funciones!para!permitir! la!
manipulación!de!colecciones!de!una! forma!más!sofisticada.!Por!ejemplo,!RxJS!define!
operadores!como!map(),!filter(),!concat(),!etc.!
Estos!operadores!reciben!opciones!de!configuración!y!devuelven!una!función!que!
consume! una! fuente! observable.! Al! ejecutar! esta! función,! el! operador! observa! los!
valores! emitidos! de! la! fuente! observable,! los! transforma! y! devuelve! un! nuevo!
observable!de!esos!valores!transformados.!
Se!usan!pipes!o! tuberías!para!vincular!operadores! (no!confundir!con! los!pipes!o!filtros! de! Angular).! Las! tuberías! permiten! combinar!múltiples! funciones! en! una! sola!
función.!La!función!pipe()!toma!como!argumentos!las!funciones!a!combinar,!y!devuelve!
una! nueva! función! que,! cuando! se! ejecuta,! ejecuta! las! funciones! asociadas!
secuencialmente.!
Un!conjunto!de!operadores!aplicados!a!un!observable!es!una!“receta”,!es!decir,!un!
conjunto!de!instrucciones!para!producir!los!valores!que!le!interesan.!En!sí!misma,!esta!
secuencia!de!funciones!no!hace!nada,!debe!llamarse!al!método!subscribe()!para!generar!
un!resultado!a!través!de!esta!“receta”.!
! Comparativa*entre*Angular*y*AngularJS.*Evolución*a*Angular*5.!
Angela!Serrano!Sánchez!! ! Página!55!!
2.7.3.! OBSERVABLES EN ANGULAR CON RXJS
Angular!utiliza!observables!para!manipular!flujos!de!datos!asincrónicos!en!eventos!
del!DOM,!en!servicios!HTTP!o!en!los!formularios!reactive!entre!otros.!!
2.7.3.1.! EVENTEMITTER
Al!escuchar!eventos!del!DOM,!se!puede!observar!un!flujo!constante!de!datos!de!lo!
que! el! usuario! está! haciendo! en! la! interfaz,! como!pulsaciones! de! teclas,! eventos! de!
ratón,!etc.!!
Angular!proporciona!la!clase!EventEmitter!que!se!utiliza!al!publicar!valores!de!un!
componente! a! través! del! decorador! @Output().! EventEmitter! extiende! la! clase!
Observable!y!proporciona!un!método!emit()!para!que!pueda!enviar!valores,!pasando!el!
valor!emitido!al!método!next!()!de!cualquier!observador!suscrito.!
2.7.3.2.! HTTP
En! los! servicios! de! http! se! escuchan! las! respuestas! del! servidor.! HttpClient! de!
Angular! devuelve! observables! en! las! llamadas! a! los!métodos! http.! Esto! proporciona!
varias!ventajas!sobre!las!APIs!de!http!basadas!en!promesas:!
•!Los!observables!no!cambian!la!respuesta!del!servidor,!pero!pueden!usar!una!serie!
de!operadores!para!transformar!los!valores!según!sea!necesario.!
•!Las!solicitudes!http!son!cancelables!mediante!el!método!unsubscribe().!
•!Las!solicitudes!se!pueden!configurar!para!obtener!actualizaciones!de!eventos!de!
progreso.!
•!Las!solicitudes!fallidas!se!pueden!reintentar!fácilmente.!
2.7.3.3.! ASYNC PIPE
El!filto!AsyncPipe!se!suscribe!a!un!observable!o!promesa!y!devuelve!el!último!valor!
que! ha! emitido.! Cuando! se! emite! un! nuevo! valor,! el! filtro! marca! el! componente! a!
verificar!para!ver!si!hay!cambios.!Cuando!el!componente!se!destruye,!la!suscripción!se!
cancela!automáticamente!para!evitar!posibles!pérdidas!de!memoria.!
2.7.3.4.! ROUTING
Router.events! proporciona! eventos! como! observables.! Puede! usar! el! operador!
filter()!de!RxJS!para!buscar!eventos!de!interés!y!suscribirse!a!ellos!para!tomar!decisiones!
basadas!en!la!secuencia!de!eventos!en!el!proceso!de!navegación.!
ActivatedRoute! es! un! servicio! inyectado! que! utiliza! observables! para! obtener!
información!sobre!una!ruta!y!sus!parámetros.!Por!ejemplo,!ActivateRoute.url!contiene!
un!observable!que!informa!la!de!ruta!actual.!
! [UPM]!Máster*en*Ingeniería*Web!
Página!56!
2.7.3.5.! REACTIVE FORMS
Las!formularios!usan!observables!para!controlar!los!valores!de!los!controles!de!los!
formularios.! Las! propiedades! de! FormControl! contienen! observables! que! generan!
eventos!de!cambio.!La!suscripción!a!una!propiedad!de!control!de!formulario!observable!
es!una!forma!de!activar!la!lógica!de!aplicación!dentro!de!la!clase!de!componente.!
2.8.! FORMULARIOS
Llegados! a! este! punto,! ya! se! han! detallado! todos! los! elementos! básicos! que!
conforman!la!arquitectura!de!Angular.!Pero!este!framework!también!aporta!una!serie!
de!herramientas,!haciendo!uso!de!los!elementes!definidos!en!los!apartados!anteriores,!
para! ampliar! la! funcionalidad! y! la! potencia! del! desarrollo! de! aplicaciones! web! con!
Angular.!
Por! ejemplo,! una! parte! esencial! del! desarrollo! web! es! permitir! al! usuario!
interactuar! con! la! aplicación.! El! elemento! estrella! en! este! caso! son! los! formularios.!
Angular!proporciona!un!módulo!completo!para!implementar!formularios,!que!facilita!la!
tarea!de!desarrollar!formularios!dinámicos!y!validar!los!datos!de!entrada!con!una!serie!
de! validadores! predefinidos,! aunque,! como! para! la! mayoría! de! elementos! del!
framework,!Angular!permite!desarrollar!validadores!personalizados.!
Este! módulo! proporciona! dos! formas! de! implementar! formulario;! basados! en!
plantillas!y!formularios!reactive.!Ambas!formas!serán!explicadas!en!detalle!en!apartados!
posteriores.!
Para! poder! comenzar! a! trabajar! con! los! formularios! de! Angular! es! necesario!
importar! el! módulo! FormsModule,! para! los! formularios! basados! en! plantillas,! o! el!
módulo!ReactiveFormsModule!en!el!caso!de!los!formularios!reactive.!Ambos!módulos!
están!incluidos!en!la!librería!@angular/forms!y!deben!añadirse!al!array!de!imports*del!módulo!principal!de!la!aplicación.!
import { FormsModule, ReactiveFormsModule } from '@angular/forms'; import { AppComponent } from './app.component'; @NgModule({ imports: [ BrowserModule, FormsModule, ReactiveFormsModule ], declarations: [ AppComponent ], providers: [], bootstrap: [ AppComponent ] })
! Comparativa*entre*Angular*y*AngularJS.*Evolución*a*Angular*5.!
Angela!Serrano!Sánchez!! ! Página!57!!
export class AppModule { }
2.8.1.! FORMULARIOS BASADOS EN PLANTILLAS
Esta! forma! de! crear! formularios! se! realiza! utilizando! la! sintaxis! de! plantillas! de!
Angular!con!las!directivas!y!técnicas!específicas!de!formularios!proporcionadas!por!el!
módulo!FormsModule.!!
En!realidad!esta!forma!de!crear!formularios!es!bastante!sencilla,!ya!que!actúa!de!la!
misma!forma!que!un!formulario!HTML!común,!salvo!por!el!hecho!de!que!se!integran!en!
él! elementos,! directivas! y! expresiones! propias! de! Angular! para! poder!manipular! los!
valores!del!formulario!desde!el!componente.!
Para!trabajar!con!la!técnica!de!los!formularios!basados!en!plantillas!se!utilizan!tres!
directivas!principalmente;!la!directiva![(ngModel)],!vista!en!el!apartado!de!Directivas!de!
Atributos,!la!directiva!ngForm!y!la!directiva!ngSubmit.!!
La!directiva!ngModel!permite!mostrar,!escuchar!y!extraer! información!al!mismo!
tiempo!de!un!elemento!del!formulario.!
La!directiva!ngForm!se!declara!en!el!tag!<form>!de!HTML!de!la!siguiente!manera;!
<form #form="ngForm">
!
Esta! directiva! complementa! la! funcionalidad! de! la! etiqueta! <form>! con!
características!adicionales;!contiene!los!controles!que!ha!creado!para!los!elementos!con!
la! directiva!ngModel! y! el! atributo!name,! y! supervisa! sus! propiedades,! incluyendo! su!validez.!A!su!vez!ngForm!contiene!su!propia!propiedad!de!validez!que!sólo!es!verdadera!
si!el!resto!controles!contenidos!en!el!formulario!también!lo!son.!
Asignar! el! atributo! name! a! los! controles! que! forman! parte! del! formulario! es!
obligatorio,!ya!que!esta!propiedad!es!requerida!por!el!módulo!de!Angular!forms!para!
registrar!el!control!con!el!formulario.!
La!directiva!ngSubmit!es!una!propiedad!de!evento!que!se!declara!en!el!formulario!
y! que! se! activará! cuando! se! pulse! el! botón! de! tipo! ‘submit’! asociado.! Al! lanzarse! el!evento,!se!ejecutará!la!expresión!registrada!que!normalmente!será!alguna!función!del!
controlador!para!persistir!los!datos!del!formulario!o!para!enviarlos!en!alguna!petición!al!
servidor.!
<form #form="ngForm" (ngSubmit)="onSubmit()">
!
! [UPM]!Máster*en*Ingeniería*Web!
Página!58!
2.8.1.1.! VALIDACIONES DE FORMULARIOS BASADOS EN
PLANTILLAS
Para! ejecutar! validaciones! sobre! un! formulario! basado! en! plantilla,! solamente!
deben!agregarse!los!mismos!atributos!de!validación!que!se!utilizan!en!las!validaciones!
de!formulario!HTML.!Angular!usa!directivas!para!unir!estos!atributos!con!funciones!de!
validación!en!el!framework.�Cada! vez! que! cambia! el! valor! de! un! control! de! formulario,! Angular! ejecuta! la!
validación!y!genera!una!lista!de!errores,!que!dan!como!resultado!un!estado!no!válido,!o!
un!estado!nulo,!lo!que!quiere!decir!que!las!valiciones!se!pasan!y!el!estado!es!válido.!
Para!crear!validadores!propios!en!un!formulario!basado!en!plantillas,!dado!que!este!
tipo!de!formularios!no!tienen!acceso!directo!a!la!instancia!del!control!del!formulario,!la!
función! de! validación! debe! incluirse! en! una! nueva! directiva.! Ésta! se! crea! como! una!
directiva!normal,!pero!debe!implementar!la!interfaz!Validator!y!sobrescribir!el!método!
validate()!utilizando! la! función!de!validación! creada.!De!este!modo!puede! integrarse!
fácilmente! con! las! formularios! de! Angular.! Luego! debe! registrarse! con! el! proveedor!
NG_VALIDATORS,!un!proveedor!con!una!colección!extensible!de!validadores.!
proveedores: [{proporcionar: NG_VALIDATORS, useExisting: ValidatorDirective, multi: true}]
2.8.2.! FORMULARIOS REACTIVOS
Este!tipo!de!formularios!facilitan!el!uso!de!un!estilo!de!programación!reactiva,!que!
favorece! la! gestión! de! datos! que! fluyen! entre! un! modelo! de! datos,! normalmente!
devuelto!por!el!servidor!y!un!modelo!de!formulario,!que!retiene!el!estado!y!los!valores!
de!los!controles!HTML!en!la!pantalla.!
Con!los!formularios!reactivos!se!crea!un!árbol!de!objetos!de!control!de!formularios!
en!la!clase!del!componente!y!los!vincula!a!controles!de!formulario!nativos!en!la!plantilla.!
Como!la!clase!del!componente!tiene!acceso!directo!tanto!a!los!datos!del!modelo!como!
a!la!estructura!de!controles!del!formulario,!se!pueden!mostrar!los!datos!del!componente!
en!el!formulario!y!devolver!al!componente!los!valores! introducidos!por!el!usuario,!es!
decir,! el! componente! puede! observar! cambios! en! los! estados! de! los! controles! del!
formulario!y!reaccionar!ante!ellos.!
Una!de!las!ventajas!que!presenta!trabajar!con!este!tipo!de!formularios!es!que!tanto!
los! valores! como! las! validaciones! son! síncronos,! lo! que! permite! tener! siempre! el!
formulario!y!sus!datos!bajo!control!directo.!
De!acuerdo!con!el!paradigma!de!la!programación!reactiva,!el!componente!preserva!
la!inmutabilidad!del!modelo!de!datos.!En!vez!de!actualizar!el!modelo!directamente,!el!
componente!extrae!los!cambios!y!los!envía!a!otro!componente!o!servicio!externo!para!
! Comparativa*entre*Angular*y*AngularJS.*Evolución*a*Angular*5.!
Angela!Serrano!Sánchez!! ! Página!59!!
que! sea! este! último! quien! los! manipule.! Cuando! se! retorne! el! nuevo! modelo! el!
componente!reflejará!los!cambios!del!modelo!actualizado.!
2.8.2.1.! FORMCONTROLS Y FORMGROUPS
Los! dos! objetos! fundamentales! en! los! formularios! reactive! de! Angular! son!FormControl!y!FormGroup.!!
Un!FormControl!representa!un!solo!campo!de!entrada:!es!la!unidad!más!pequeña!
del!formulario.!Este!objeto!encapsula!el!valor!del!campo!y!su!estado,!es!decir,!si!es!válido!
o!tiene!errores!de!validación.!
Para! crear! formularios,! se! crean! tantos! FormControls! como! elementos! del!
formulario!se!necesiten,!a!los!que!luego!se!asocian!metadatos!y!lógica.!El!form!control!
se! define! en! la! clase!del! componente! y! luego!puede! asociarse! al!DOM!mediante!un!
enlace! de! propiedad! formControl.! Por! ejemplo,! el! componente! podría! definir! el!
siguiente!elemento;!
export class AppComponent { name = new FormControl(); }
!
Y!en!la!plantilla!se!representaría!como;!
<input type = "text" [formControl] = "name" />
!
La! forma! de! administrar!múltiples! FormControls! es!mediante! el! uso! de! la! clase!
FormGroups.!Esta!clase!devuelve!un!objeto!con!parejas!de!clave/valor!proporcionando!
una! forma! de! almacenar! y! validar! el! estado! de! múltiples! instancias! de! elementos!
FormControl.!Siguiendo!con!el!ejemplo!anterior,!en!la!clase!se!definiría!lo!siguiente;!
export class AppComponent { appForm = new FormGroup ({ name: new FormControl() }); }
!
Y!en!la!plantilla!se!representaría!como;!
<form [formGroup]="heroForm"> <input class="form-control" formControlName="name"> </form>
! [UPM]!Máster*en*Ingeniería*Web!
Página!60!
2.8.2.2.! FORMBUILDER
La!clase!FormBuilder!se!utiliza!para!configurar!formularios!de!forma!más!flexible.!
Esta!clase!ayuda!a!crear!elementos!FormGroup!y!FormControl!de!forma!más!sencilla.!
La!forma!de!utilizar!esta!clase!es!la!siguiente;!
export class AppComponent { appForm: FormGroup; // Se declara un elemento de tipo FormGroup constructor(private fb: FormBuilder) { // se inyecta FormBuilder this.createForm(); } createForm() { this.appForm = this.fb.group({ name: '', // se declaran los FormControl (par clave/valor) }); } }
!
Se!debe!inyectar!en!la!clase!del!componente!el!elemento!FormBuilder!y!después!se!
crean!los!elementos!del!formulario!mediante!su!función!.group(),!que!es!un!método!de!
factoría!que!devuelve!un!elemento!FormGroup.!
Esta! clase! también!permite! crear! formularios! anidados.! Simplemente!al! crear!el!
formulario,!en!una!de!las!propiedades!definidas!también!se!llamará!al!método!.group().!
createForm() { this.appForm = this.fb.group({ name: '', // <--- FormControl othername: this.fb.group({ ... }) }); }
!
Así!mismo!la!clase!FormGroup!proporciona!métodos!para!inicializar!los!controles!
de! los! formularios;! .setValues()! se! utiliza! para! inicializar! todos! los! controles! y!
.patchValues()!es!para!inicializar!controles!específicos.!
También!proporciona!el!método!.reset()!en!caso!de!querer!incializar!el!formulario!
por!defecto!o!dejar!los!valores!vacíos.!
2.8.2.3.! VALIDACIONES DE FORMULARIOS REACTIVOS
En!el!caso!de!los!formularios!reactivos,!en!vez!de!añadir!los!validadores!a!través!de!
atributos!de!la!plantilla!o!directivas,!se!añaden!funciones!de!validación!directamente!al!
! Comparativa*entre*Angular*y*AngularJS.*Evolución*a*Angular*5.!
Angela!Serrano!Sánchez!! ! Página!61!!
control! del! formulario! en! la! clase! del! componente.! Angular! se! encarga! entonces! de!
llamar!a!estas!funciones!cada!vez!que!el!valor!del!control!cambia.!
Existen!dos!tipos!de!funciones!de!validación,!síncronas!y!asíncronas.!Los!validadores!
síncronos!toman!de!forma!inmediata!la!instancia!del!control!y!devuelven!un!conjunto!
de!errores!de!validación,!o!el!valor!null*si!no!se!ha!producido!ningún!error.!!Los! validadores! asíncronos! reciben! la! instancia! del! control! y! devuelven! una!
promesa!u!observable!que!emite!un!conjunto!de!errores!de!validación!o,!como!ocurre!
en!el!caso!anterior,!el!valor!null*si!no!hay!errores.!Las!funciones!de!ambos!tipos!de!validación!pueden!pasarse!como!tercer!parámetro!
cuando!se!instancia!el!FormControl.!
Por!motivos!de!rendimiento,!los!validadores!asíncronos!sólo!se!ejecutan!si!todos!
los!validadores!síncronos!se!han!ejecutado!correctamente,!es!decir,!no!han!devuelto!
errores.!
Del!mismo!modo!que!en!los!formularios!basados!en!plantilla!pueden!utilizarse!los!
atributos! de! validación! típicos! de!HTML,! aunque! en! este! caso! las! validaciones! están!
disponibles!como!funciones!para!los!formularios!reactivos!a!través!de!la!clase!Validators.!
name = new FormControl(this.name, [ Validators.required ]);
!
Aunque! también! pueden! crearse! validadores! propios,! en! cuyo! caso! la! función!
creada!como!validador!se!pasa!por!parámetro!a!la!instancia!del!FormControl.!
2.9.! NAVEGACIÓN Y ROUTING
En!el! desarrollo!web,! el! enrutamiento!o! routing! significa!dividir! la! aplicación!en!áreas!diferentes,!normalmente!basadas!en!reglas!derivadas!de! la!URL!que!haya!en!el!
navegador!en!ese!momento.!
En!el!caso!de!las!aplicaciones!web,!es!recomendable!utilizar!la!técnica!de!routing!por!las!múltiples!ventajas!que!presenta;!además!de!dividir! la!aplicación!en!diferentes!
áreas!para!facilitara!la!consulta!y!la!búsqueda!de!información,!es!posible!proteger!dichas!
áreas!de!accesos! indeseados!o!acciones! sospechosas,!aplicando! reglas!y!validaciones!
sobre!esas!rutas.!También!permite!mantener!el!estado!de!la!aplicación,!por!ejemplo,!si!
la!página!fuese!de!contenido!único,!al!refrescar!la!página!se!perdería!la!localización!en!
la! que! se! situaba! la! aplicación! justo! en!el!momento! anterior! a! la! actualización!de! la!
página!y!tampoco!sería!posible!buscar! la! localización!de!dicha!área!directamente,!sin!
acceder!primero!a!la!página!inicial!de!la!aplicación.!
En!el!caso!del!enrutamiento!en!el! lado!del! servidor!cuando! la!URL!cambia!en!el!
navegador,!éste!envía!una!petición!al!servidor,!que!accede!al!controlador!requerido!y!
! [UPM]!Máster*en*Ingeniería*Web!
Página!62!
dependiendo!de! la!URL!solicitada!devuelve! los!datos!necesarios!para!que!puedan!ser!
renderizados!y!!mostrados!por!el!navegador!tal!y!como!se!muestra!en!la!Imagen!11.!
!Imagen*11.*Enrutamiento*en*el*lado*del*servidor*
En! el! caso! de!Angular,! se! aplica! lo! que! se! denomina! enrutamiento! del! lado! del!
cliente.!Es!muy!parecido!en!concepto!al!enrutamiento!en!el!servidor,!pero!difieren!en!la!
implementación.!Cuando!se!realiza!la!navegación!en!el!lado!del!cliente!no!siempre!va!a!
ser!necesario!mandar!una!petición!al!servidor.!En!las!ocasiones!en!las!que!se!realice!una!
petición! al! servidor,! éste! enviará! como! respuesta! una! única! página! y! será!
responsabilidad!del!cliente!llevar!a!cabo!las!modificaciones!necesarias!sobre!esta!página.!!
Este!tipo!de!enrutamiento!se!representa!en!la!imagen!12.!
!Imagen*12.*Enrutamiento*en*el*lado*del*cliente*
Estas!aplicaciones!reciben!el!nombre!de!“Single!Page!Apps”! (SPA)!y!presenta! las!
siguientes!ventajas;!
1.!Es!más!rápido!ya!que,!en!lugar!de!hacer!una!petición!a!algún!servidor!remoto!con!
un!!consumo!de!tiempo!considerable,!cada!vez!que!la!URL!cambia,!la!aplicación!actualiza!
la!página!mucho!más!rápido.!
2.!No!requiere!tanto!ancho!de!banda!porque!no!se!envía!una!gran!página!html!por!
cada!cambio!de!URL,!sino!que!podría!llamarse!a!una!API!más!pequeña!que!devuelve!solo!
los!datos!suficientes!para!representar!el!cambio!en!la!página.!
! Comparativa*entre*Angular*y*AngularJS.*Evolución*a*Angular*5.!
Angela!Serrano!Sánchez!! ! Página!63!!
3.! Un! único! desarrollador! fronFend! puede! construir! la! mayor! parte! de! la!
funcionalidad!de!la!aplicación,!en!lugar!de!dividir!el!esfuerzo!con!un!desarrollador!backFend.!
Para!cubrir!toda!la!funcionalidad!anterior,!Angular!dispone!de!un!paquete!con!una!
serie!módulos!y!clases!que!permiten!implementar!aplicaciones!web!con!un!sistema!de!
navegación!y!enrutamiento!con!todas!las!ventajas!de!las!aplicaciones!Single!Page!App.!
El!enrutador!angular!puede!interpretar!una!URL!como!una!instrucción!para!navegar!
a! la! ! vista! de! un! componente.! Ésta! puede! pasarle! al! componente! en! cuestión,!
parámetros!que!le!ayudarán!a!decidir!qué!contenido!específico!presentar!o!qué!acciones!
llevar!a! cabo.!El!enrutador!vincula!una!página!a!un!enlace!y!navega!a!ella! cuando!el!
usuario!accede!a!través!de!ese!enlace,!aunque!también!puede!llevarse!a!cabo!a!través!
de!un!botón,!desde!la!selección!de!algún!elemento!en!un!desplegable!o!en!respuesta!a!
algún! otro! estímulo.! El! enrutador! se! encarga! además! de! registrar! la! actividad! en! el!
historial!del!navegador!para!que! los!botones!de!atrás!y!adelante!funcionen!de!forma!
correcta.!
2.9.1.! CONFIGURACIÓN
Para!poder!utilizar!el!enrutador!o!Router!de!Angular!es!necesario!definir!una!ruta!inicial! con! el! elemento! <base>! de! HTML! y! después! importar! en! la! aplicación! los!
elementos!Router!y!RouterModule!del!paquete!@angular/router.!
Añadir!el!elemento!<base!href=”/”>!a!la!página!inicial!de!la!aplicación!es!necesario!
para!poder!indicar!al!enrutador!cómo!componer!las!URL!de!navegación.!!
El!enrutador!utiliza!el!método!history.pushState()!de!HTML5!para! la!navegación.!
Gracias!a!este!método!se!consigue!que!las!URL!internas!de!la!aplicación!se!visualicen!
como!las!URL!que!utiliza!el!servidor.!Este!tipo!de!URL!se!conocen!como!rutas!“HTML5!
style”!y!es!el!que!utiliza!el!Router!de!Angular!por!defecto.!El!navegador!utiliza!el!valor!de!<base!href>!para!prefijar!las!URL!relativas!al!hacer!
referencia! a! archivos! CSS,! scripts! e! imágenes,! sin! este! elemento! no! funcionaría! el!
método!pushState().!!!Después! se! deben! cargar! los! módulos! de! Angular! necesarios! para! aportar! la!
funcionalidad!de!navegación.!Esto!se!hace!principalmente!importando!el!objeto!Routes!
y!el!módulo!RouterModule.!
Una!aplicación!angular!con!routing!tiene!una!instancia!singleton!del!servicio!Router.!Cuando!la!URL!del!navegador!cambia,!el!enrutador!busca!la!ruta!correspondiente!desde!
la! cual! puede! determinar! el! componente! que! se! mostrará.! El! enrutador! debe!
configurarse!con!una!lista!de!definición!de!rutas.!Para!ello!se!crea!un!array!de!objetos!
Routes,!donde!se!declaran!estas!definiciones.!Un!ejemplo!de!configuración!podría!ser!
como!el!que!se!muestra!a!continuación;!
const appRoutes: Routes = [ { path: 'firstpath', component: FirstPathComponent },(1)
! [UPM]!Máster*en*Ingeniería*Web!
Página!64!
{ path: 'secondpath/:id', component: SecondPathComponent },(2) { path: 'data',(3) component: DataComponent, data: { title: 'Heroes List' } }, { path: 'parent',(4) component: ParentComponent, children: [ { path: 'children', component: ChildrenComponent } ] } { path: '',(5) redirectTo: '/firstpath', pathMatch: 'full' }, { path: '**', component: PageNotFoundComponent }(6) ];
!
En!el!ejemplo!anterior,!se!observan!diferentes!formas!de!definir!las!rutas!de!una!
aplicación.!De!forma!común!cada!objeto!del!array!Routes,!constará!de!una!propiedad!
path!que!recibe!como!valor!el!segmento!de!la!URL!que!indicará!la!ruta!y!una!propiedad!
component!que!indicará!el!componente!asociado!a!la!ruta!(1).!!
A!las!rutas!declaradas!en!la!propiedad!path,!se!les!puede!indicar!la!existencia!de!
parámetros,! como! ocurre! en! el! segundo! caso! del! ejemplo! anterior! (2).! En! la! URL!
‘secondpath/:id’,!el!elemento!:id!es!un!token!que!se!asigna!a!la!ruta.!Se!denomina!como!
variable!o!parámetro!de!ruta,!y!se!especifica!su!condición!de!parámetro!nombrando!el!
elemento!con!dos!puntos!delante.!El!componente!correspondiente!utilizará!el!valor!de!
este!token!para!encontrar!y!presentar!la!información!asociada!a!ese!valor.!Para!recoger!
el! valor! de! ese! parámetro,! Angular! proporciona! la! clase! ActivatedRoute,! que! será!
tratada!en!detalle!más!adelante.!
La! propiedad! data! en! la! tercera! ruta! se! usa! para! almacenar! datos! arbitrarios!
asociados! a! esa! ruta! específica! (3).! Esta! propiedad! es! accesible! dentro! de! cada! ruta!
activada.!Se!usa!principalmente!para!almacenar!elementos!como!títulos!de!página,!texto!
de!navegación!y!otros!datos!estáticos!de!solo!lectura.!
La!cuarta!ruta!define!una!nueva!propiedad!children,!donde!se!definirán!lo!que!se!
denomina!como!rutas!hijas!(4).!Lo!que!se!define!en!esta!propiedad!también!son!rutas,!
por!lo!que!podría!decirse!que!es!una!anidación!de!rutas.!Las!rutas!hijas!extienden!el!path!
de! la! ruta! padre,! con! cada! anidación! en! la! definición! de! rutas! se! agrega! una! barra!
seguido!del!path!definido!en!la!ruta,!a!menos!que!alguna!de!ellas!se!encuentre!vacía.!
Por!entender!el!concepto!algo!mejor,!en!el!ejemplo!anterior!la!URL!formada!quedaría!
! Comparativa*entre*Angular*y*AngularJS.*Evolución*a*Angular*5.!
Angela!Serrano!Sánchez!! ! Página!65!!
como!/parent/children.!Con!esta!ruta,!la!aplicación!mostraría!tanto!la!información!del!
componente!indicado!en!la!ruta!padre!como!la!del!componente!de!la!ruta!hija.!
El!siguiente!caso!de!ruta!definido!en!el!ejemplo!es!algo!particular.!Se!observa!que!
no!define!una!propiedad!component!como!los!anteriores,!sino!que!define!la!propiedad!
redirectTo*(5).!Esta!propiedad!se!utiliza!principalmente!para!redirigir!la!ruta!de!inicio!de!
la!aplicación! (que!por!defecto! suele! ser! ‘/’)! al! componente! requerido.!En!el! caso!del!
ejemplo!anterior!se!redirige!la!ruta!por!defecto!a!/firstpath,!por!lo!que!se!ejecutará!el!
componente!FirstPathComponent.!!
Por!último,!la!propiedad!path!de!la!última!ruta!mostrada!en!el!ejemplo,!es!distinta!
a!las!definidas!en!las!otras!rutas.!En!vez!de!especificar!una!URL,!los!dos!asteriscos!indican!
que! es! una! ruta! ‘comodín’,! en! caso! de! no! encontrar! la! URL! solicitada,! el! enrutador!
seleccionará!esta!ultima!ruta!mostrando!el!componente!asociado!(6).!
El!orden!de!las!rutas!en!la!configuración!importa!y!esto!es!por!diseño.!El!enrutador!
utiliza!la!estrategia!de!‘firstFmatch*wins’!(primera!en!coincidir!gana)!al!buscar!las!rutas,!
por! lo!que! las!rutas!más!específicas!se!deben!colocar!por!encima!de! las!rutas!menos!
específicas.!En! la!configuración!anterior,! las!rutas!con!una!ruta!estática!se!enumeran!
primero,!después!se!ubica!la!ruta!vacía,!que!coincide!con!la!ruta!predeterminada!y!por!
último!la!ruta!del!comodín!porque!coincide!con!todas!las!URL!y!debe!seleccionarse!solo!
si!no!hay!otras!rutas!coincidentes.!
Para!poder!utilizar! la!configuración!anterior,! la!variable!appRoutes!creada!con!la!
definición! de! rutas! se! pasará! por! parámetro! al! método! forRoot()! del! módulo!
RouterModule.! Esto! a! su! vez! devolverá! un! módulo! que! contiene! el! proveedor! de!
servicios! del! enrutador! configurado,! más! otros! proveedores! que! la! biblioteca! de!
enrutamiento! requiere.! Una! vez! que! la! aplicación! se! inicia,! el! enrutador! realiza! la!
navegación!inicial!en!función!de!la!URL!actual!del!navegador!(Google,!Angular,!2018).!
Añadir!el!módulo!RouterModule!al!array!de!imports!de!la!directiva!@NgModule!del!
módulo!principal!es!suficiente!para!configuraciones!con!enrutamiento!simple,!pero!a!
medida! que! la! aplicación! crece,! es! conveniente! configurar! el! enrutamiento! de! la!
aplicación!en!uno!o!varios!archivos!separados!y!crear!lo!que!se!conoce!como!módulo!de!
enrutamiento,! un! tipo! especial! de! módulo! de! servicio! dedicado! a! funciones! de!
enrutamiento!en!módulos!característicos.!
El!módulo!de!enrutamiento!tiene!varias!características:!
•! Se! centra! en! la! funcionalidad! de! enrutamiento! abstrayendo! al! resto! de!funcionalidades!de!la!aplicación.!!•! Proporciona!un!módulo!individual!para!reemplazar!o!eliminar!cuando!se!prueba!la!aplicación.!•! No!declara!componentes.!•! Provee! una! ubicación! bien! definida! para! los! proveedores! de! servicios! de!enrutamiento,!incluyendo!guardias!y!resolvers.!
Pueden!existir!varios!módulos!de!enrutamiento,!aunque!los!siguientes,!si!se!definen!
para!módulos!específicos,!utilizarán!el!método! .forChild()!en! lugar!de! .forRoot(),!que!
especifica!que!el!módulo!será!importado!en!un!módulo!que!no!es!el!principal.!
! [UPM]!Máster*en*Ingeniería*Web!
Página!66!
2.9.2.! DIRECTIVAS
2.9.2.1.! ROUTER OUTLET
Una! vez! configurada! la! definición! de! rutas,! para! que! el! enrutador! sea! capaz! de!
localizar!y!mostrar!el!componente!correspondiente!a!la!URL!solicitada,!debe!colocarse!
en!la!vista!contenedora!la!directiva!RouterOutlet.!
Esta! directiva! está! contenida! en! la! librería! del! enrutador! e! indica! el! lugar! en! la!
plantilla!en!el!que!se!debe!mostrar!la!vista!del!componente!asociado!a!la!ruta.!
El!enrutador!agrega!el!elemento!<routerooutlet>!al!DOM!y!luego!inserta!la!vista!del!
elemento!navegado!inmediatamente!después!de!<routerooutlet>.!
2.9.2.2.! ROUTER LINK
Router!Link!es!la!directiva!encargada!de!permitir!la!navegación!entre!los!distintos!
componentes!de!la!aplicación.!Se!suele!asociar!a!elementos!de!navegación!HTML!como!
hipervínculos!o!botones.!
Al! asociar! la! directiva! a! esos! elementos! el! enrutador! es! capaz! de! controlar! su!
comportamiento.!Un!ejemplo!sería!el!siguiente;!
<a routerLink=”/path”>Path 1</a>
!
En!este!caso! routerLink!es!una!directiva!de!atributo,!a! la!que!se! le!asocia!como!
expresión!el!path!de!alguna!de! las!rutas!definidas!en! la!configuración.!En! la! línea!del!
ejemplo! anterior,! se! produce! la! navegación! a! la! ruta! /path,! pero! hay! veces! que! se!
necesita!navegar!a!un!elemento!concreto!de!la!aplicación!por!lo!que!puede!ser!necesario!
indicar!a!la!ruta!un!parámetro!de!búsqueda.!Como!se!ha!visto!en!el!apartado!anterior,!
se!pueden!especificar!en! la!configuración!URLs!con!parámetros,!como!era!el!caso!de!
path:!'secondpath/:id'.
Para!indicar!al!navegador!el!elemento!:id!de!la!ruta,!la!directiva!routerLink!permite!
seleccionar!y!añadir!al!path!el!valor!del!id!necesario.!Éste!valor!se!indica!dentro!de!lo!
que!se!denomina!cómo!‘link*parameters*array’!compuesto!por!el!path!destino!de!la!ruta!
y! los!parámetros!(que!pueden!ser!opcionales!u!obligatorios)!que!necesita! la!URL.!Por!
ejemplo,!asumiendo!que!el!componente!en!el!que!se!encuentra!la!aplicación!consta!de!
una!serie!de!elementos!u!objetos!del!mismo!tipo,!y!que!ese!tipo!de!objeto!consta!de!
varios!atributos,!entre!ellos!un!valor!de!id,!la!aplicación!podrá!acceder!a!los!detalles!de!
ese!objeto!concreto!a!través!de!su!id,!añadiéndolo!al!array!de!parámetros!de!la!directiva!
de!la!siguiente!forma;!
<a [routerLink]=[“/path”, objeto.id]>Path 1</a>
!
! Comparativa*entre*Angular*y*AngularJS.*Evolución*a*Angular*5.!
Angela!Serrano!Sánchez!! ! Página!67!!
Asumiendo!que! el! valor! de! ‘objeto.id’! del! ejemplo! es! igual! a! 1,! la!URL! a! la! que!
navegará!la!aplicación!cuando!se!acceda!al!link!de!Path!1!será!/path/1!
2.9.2.3.! ROUTERLINKACTIVE
Esta!directiva,!también!se!usa!en!los!elementos!de!navegación!de!la!plantilla!HTML,!
y!puede!utilizarse!conjuntamente!con!la!directiva!anterior,!ya!que!routerLinkActive!se!
utiliza!para!aplicar!ciertas!reglas!de!estilo!CSS!al!elemento!cuya!ruta!se!encuentra!activa.!
También! se! trata! de! una! directiva! de! atributo! por! lo! que! la! expresión! asociada! a! la!
directiva!es!una!serie!de!clases!CSS!que!se!aplicarán!al!elemento!contenedor!basado!en!
el!estado!de!la!ruta.!
<a [routerLink]=[“/path”, objeto.id] routerLinkActive=”class1 class2”>Path 1</a>
!
La! aplicación! sobre! un! elemento! de! la! directiva! RouterLinkActive! funciona! en!
cascada!descendiendo!a!través!de! los!distintos!niveles!del!árbol!de!enrutamiento,!de!
forma!que!los!links!de!los!elementos!padre!y!los!elementos!hijos!pueden!estar!activos!a!
la!vez,!a!no!ser!que!se!especifique!el!comportamiento!contrario,!sobreescribiendo!este!
comportamiento,! asociando! la! entrada! de! la! directiva! [routerlinkActiveOptions]! a! la!
expresión!{exact:!true}.!Con!esta!condición!sólo!la!URL!del!path!que!coincida!con!la!URL!
especificada!será!la!que!se!marque!como!ruta!activa.!
2.9.3.! ACTIVATED ROUTES
Si!en! la!aplicación!se!especifica!una!ruta!con!parámetros,!es!necesario! tener! las!
herramientas!y!los!mecanismos!adecuados!para!poder!recuperar!esos!valores.!Para!ello!
Angular!dispone!de!la!interfaz!RouterState!y!de!la!clase!ActivatedRoute.!
RouterState!es!una!interfaz!de!la!librería!@angular/route!que!representa!el!estado!
del!enrutador.!!
Después!de!cada!ciclo!de!vida!de!navegación!finalizado!con!éxito,!el!enrutador!crea!
un!árbol!de!objetos!ActivatedRoute!que!conforman!el!estado!actual!del!enrutador.!Este!
árbol!de!rutas!activadas!compone!el!RouterState,!donde!cada!nodo!del!árbol!conoce!los!
segmentos! de!URL! "consumidos",! los! parámetros! extraídos! y! los! datos! resueltos.! Se!
puede!acceder!al!RouterState!actual!desde!cualquier!lugar!de!la!aplicación!utilizando!el!
servicio!Router!y!la!propiedad!routerState.!
Cada!ActivatedRoute!en!el!RouterState!proporciona!métodos!para!recorrer!arriba!
y!abajo!el!árbol!de!rutas!para!obtener!información.!Los!elementos!de!ActivatedRoute!
que!permiten!hacer!lo!anterior!son!los!siguientes;!
•! url!o>!Observable!de!la!ruta,!representado!como!un!array!de!strings!con!cada!una!de!las!partes!que!componen!la!ruta.!!
•! data!o>!Observable!que!contiene!un!objeto!data!proporcionado!por!la!ruta.!!
! [UPM]!Máster*en*Ingeniería*Web!
Página!68!
•! paramMap!o>!Observable!que!contiene!un!mapa!con!los!parámetros!de!la!ruta.!!•! queryParamMap!o>!Observale!que!contiene!un!mapa!de!parámetros!de!la!query!
disponibles!para!todas!las!rutas.!!•! fragment! o>!Observable!de!un! fragmento!de! la!URL!disponible!para! todas! las!
rutas!•! outlet!o>!El!nombre!del!RouterOutlet!utilizado!para!renderizar!la!ruta.!!•! routeConfig!o>!La!configuración!de!ruta!usada!por!el!enrutador.!•! parent!o>!Contiene!la!ruta!padre!ActivatedRoute!cuando!la!ruta!es!una!ruta!hija.!•! firstChild!o>!Contiene!la!primera!ActivatedRoute!en!la!lista!de!las!rutas!hijas!de!la!
ruta!actual.!•! children!o>!Contiendo!todas!las!rutas!hijas!activas!bajo!la!ruta!actual.!
Para!utilizar!esta!funcionalidad,!en!el!componente!al!que!apunta!la!URL!actual,!se!
importa!y!se! inyecta! la!clase!ActivatedRoute! como!dependencia!en!el!constructor!de!
éste.! Luego,!preferiblemente!en!el!método!ngOnInit,! se! recogerá!el!parámetro!o! los!
parámetros!de!la!URL,!utilizando!la!propiedad!paramMap;!
ngOnInit() { this.object = this.route.paramMap.subscribe( (params: ParamMap) => { this.id = params.get('id') } ); }
!
En! este! ejemplo,! se! recupera! el! mapa! de! parámetros! de! la! ruta! desde! un!
Observable.!Esto!implica!que!el!mapa!de!parámetros!puede!cambiar!durante!la!vida!útil!
de!este!componente.!Por!defecto,!el!enrutador!reutiliza!una!instancia!del!componente!
cuando! vuelve! a! navegar! al! mismo! tipo! de! componente! sin! visitar! primero! un!
componente!diferente.!Los!parámetros!de!ruta!podrían!cambiar!cada!vez.!No!se!desea!
que!el!enrutador!elimine!la!instancia!actual!del!componente!del!DOM!solo!para!volver!a!
crearla! para! la! siguiente! identificación.! Es! mejor! simplemente! reutilizar! la! misma!
instancia!de!componente!y!actualizar!el!parámetro.!
Desafortunadamente,! ngOnInit! solo! se! llama! una! vez! por! instanciación! de!
componente.!Necesita!una!forma!de!detectar!cuándo!los!parámetros!de!ruta!cambian!
desde!la!misma!instancia.!La!propiedad!paramMap!se!encarga!de!manejar!esto.!
2.9.4.! GUARDAS Y RESOLVERS
No!siempre!debe!permitirse!a!un!usuario!navegar!a!todas!las!rutas!de!la!aplicación.!
Para!verificar!estos!permisos,!pueden!implementarse!lo!que!se!denomina!como!guardas!
en!Angular.!
! Comparativa*entre*Angular*y*AngularJS.*Evolución*a*Angular*5.!
Angela!Serrano!Sánchez!! ! Página!69!!
Estas!guardas!se!desarrollan!como!servicios!en! la!aplicación!que! implementarán!
una! determinada! interfaz,! dependiendo! de! lo! que! sea! necesario! comprobar,! y! se!
asociarán!posteriormente!a!una!ruta,!para!que!se!valide!o!no!el!acceso!a!ésta.!
El! valor! de! retorno! de! una! guarda! controla! el! comportamiento! del! enrutador!
dependiendo! de! si! la! respuesta! devuelve! verdadero,! continuando! el! proceso! de!
navegación,!o!si!devuelve!falso,!en!cuyo!caso!la!navegación!se!cancela.!
Las!interfaces!que!Angular!proporciona!para!aplicar!una!guarda!a!una!ruta!son!las!
siguientes.!
•! CanActivate:!Se!utiliza!principalmente!para!verificar!si!un!usuario!tiene!permisos!
(por! su! rol! o! porque! requiera! estar! autenticado)! para! navegar! a! una! ruta!
concreta.!
•! CanActivateChild:! Igual! que! la! anterior,! aunque! se! utiliza! en! rutas! hijas! de! la!
configuración.!
•! CanDeactivate:!Se!utiliza!cuando,!si!un!usuario!ha!ido!acumulando!cambios!que!
no!han!sido!comunicados!al!servidor!o!se!encuentran!pendientes!de!validación,!
esta!guarda!da!la!oportunidad!al!usuario!de!guardar!o!cancelar!los!cambios!antes!
de!navegar!a!otra!ruta!de!la!aplicación.!Si!el!usuario!decide!salvar!los!cambios,!
canDeactivate!mantiene!la!ruta!actual!de!forma!asíncrona!hasta!que!el!servidor!
retorna!su!respuesta,!y!si!todo!va!bien!redirige!al!usuario!a!la!ruta!donde!quería!
navegar!antes!de!guardar!los!cambios.!
•! CanLoad:!Esta!interfaz!permite!cargar!módulos!de!la!aplicación!de!forma!diferida!
(lazy*loading),!a!petición!del!usuario.!•! Resolver:! Asignar! un! resolver! a! una! determinada! ruta! permite! recuperar! los!
datos!del!servidor,!antes!de!navegar!a!la!ruta!activada.!De!esta!forma,!cuando!se!
acceda!a!la!vista!los!datos!ya!estarán!disponibles!y!no!habrá!que!esperar!a!que!
éstos!empiecen!a!cargarse!para!mostrarlos.!En!resumen,!retrasa!la!renderización!
del! componentes! enrutado! hasta! que! se! hayan! obtenido! todos! los! datos!
necesarios.!
2.10.! CONEXIÓN CON EL SERVIDOR Y HTTPCLIENT
La!mayoría!de!las!aplicaciones!frontFend!se!comunican!con!los!servicios!del!backFend!a!través!del!protocolo!HTTP.!!
Cuando! se! hacen! llamadas! a! un! servidor! externo,! el! usuario! debe! ser! capaz! de!
interactuar!con!la!aplicación!sin!que!ésta!se!congele!hasta!que!la!solicitud!HTTP!vuelva!
del!servidor.!Para!lograr!este!efecto,!las!solicitudes!HTTP!deben!ser!asincrónicas.!
En!JavaScript,!generalmente!hay!tres!enfoques!para!tratar!con!el!código!asíncrono:!
1.!Devolución!de!llamada!
2.!Promesas!
! [UPM]!Máster*en*Ingeniería*Web!
Página!70!
3.!Observables!
En!Angular,!el!método!más!usado!para!tratar!con!el!código!asíncrono!es!mediante!
el!uso!de!Observables.!
Los!navegadores!modernos!admiten!dos!APIs!diferentes!para!realizar!solicitudes!
HTTP:!la!interfaz!XMLHttpRequest!y!la!fetch!()!API.!
La!clase!HttpClient!de!@angular/common/http!proporciona!una!API!simplificada!
que!se!basa!en!la!interfaz!XMLHttpRequest!expuesta!por!los!navegadores.!Los!beneficios!
adicionales! de! HttpClient! incluyen! características! de! testing,! objetos! de! solicitud! y!
respuesta!tipados,!intercepción!de!solicitudes!y!respuestas,!APIs!observables!y!manejo!
simplificado!de!errores.!
Para! usar! esta! funcionalidad! se! debe! importar! el! módulo! HttClientModule,!
generalmente!en!el!módulo!principal,!para!poder!inyectarlo!después!en!cualquier!otro!
elemento!de!la!aplicación!que!lo!necesite.!
Salvo! excepciones,! los! elementos! en! los! que! se! inyectará! este! servicio,! serán!
precisamente!otros!servicios.!Como!se!vio!en!el!apartado!de!Servicios!e! Inyección!de!
dependencias,!éstos!son!los!encargados!de!realizar!el!acceso!a!los!datos,!mientras!que!
la!función!del!componente!recaerá!principalmente!en!mostrar!esos!datos.!De!esta!forma!
se!abstraerá!al! componente!del! acceso!a! los!datos! inyectando!un!único! servicio!que!
aporte!la!funcionalidad!necesaria.!
2.10.1.! COMUNICACIÓN CON EL SERVIDOR
Como!es!normal,!ya!que!HttpClient!se!basa!en!el!protocolo!http!para!comunicarse!
con!el!servidor,!su!utilización!permite!realizar! las!operaciones!típicas!de!peticiones!al!
servidor!como!son!GET,!POST,!PUT!y!DELETE.!
Una!vez!que!ha!sido!inyectado!el!servicio!en!el!constructor!del!elemento!donde!va!
a!utilizarse,!a!través!de!esa!clase!se!da!acceso!a!los!métodos!.get(),!.post(),!.delete()!y!
put()!cuya!configuración!será!definida!en!detalle!a!continuación.!
2.10.1.1.! PETICIÓN GET
La!petición!HttpClient.get()!se!utiliza!para!recuperar!datos!del!servidor.!Por!defecto,!
este!método!recupera!la!respuesta!del!servidor!en!formato!JSON!y!la!transforma!en!un!
objeto.!El!objeto!devuelto!puede!ser!tipado!si!se!indica!a!la!petición!qué!tipo!de!objeto!
espera!de!la!llamada!al!servidor.!
!
this.http.get<Object>(url);
!
Cuando!se!realice!la!suscripción!a!la!llamada!GET,!también!debe!indicarse!el!tipo!de!
objeto!que!devuelve!el!observable.!
! Comparativa*entre*Angular*y*AngularJS.*Evolución*a*Angular*5.!
Angela!Serrano!Sánchez!! ! Página!71!!
this.http.get<Object>(url).subscribe( (data: Object) => this.result = {data} )
!
Hay!ocasiones!en!que,!más!allá!de!recuperar!la!información!devuelta!en!el!cuerpo!
de!la!respuesta,!el!servidor!envía!otra!información!que!también!debe!recogerse!de!la!
petición! GET,! como! pueden! ser! cabeceras! o! códigos! de! estado! que! indican! ciertas!
condiciones! importantes! en! el! flujo! de! la! aplicación.! Para! recuperar! la! respuesta!
completa!HttpClient!dispone!de!la!propiedad!{!observe:!‘response’!},!que!se!añade!como!
parámetro!a!la!petición!get;! this.http.get<Object>(url, { observe: 'response' });
!
Esta! petición! devuelve! un! observable! del! tipo! HttpResponse,! en! vez! de! la!
información!JSON!del!cuerpo!de!la!respuesta.!
Si!en!lugar!de!recuperar!la!información!en!formato!JSON,!se!quisiese!recuperar!en!
otro! formato,!en! la!petición!debe! indicarse!el! tipo!específico!utilizando! la!propiedad!
responseType,! de! forma! similar! a! como! se! utiliza! la! opción! observe! en! el! ejemplo!
anterior.!
this.http.get<Object>(url, { responseType: 'text' });
!
Las!peticiones!GET!se!caracterizan!por!ser!idempotentes,!es!decir,!se!espera!que!la!
misma! petición! devuelva! siempre! el! mismo! resultado.! Además! son! cacheables! y! la!
petición!permanece!en!el!historial!de!navegación.!
2.10.1.2.! PETICIÓN POST
El! método! HttpClient.post()! además! de! enviar! una! URL! como! parámetro! en! la!
petición,!puede!requerir!dos!parámetros!más;!el!objeto!con!los!datos!a!enviar!al!servidor!
en!el! cuerpo!de! la! solicitud! y!el! parámetro!httpOptions;! parámetros! adicionales!que!
puede!necesitar!la!petición!como!por!ejemplo,!las!cabeceras.!
this.http.post<Object>(url, object, httpOptions);
Las! peticiones! POST! difieren! de! las! solicitudes! GET! en! algunas! particularidades!
como!que! éstas! llamadas! no! son! idempontentes,! ya! que! cada! llamada! producirá! un!
resultado!diferente.!Tampoco!podrán!ser!cacheadas!ni!se!mantendrán!en!el!histórico!de!
navegación!y!generalmente!usarán!el!cuerpo!de!la!petición!HTTP!tanto!para!enviar!como!
para!recibir!datos.!
! [UPM]!Máster*en*Ingeniería*Web!
Página!72!
2.10.1.3.! PETICIÓN PUT
La!petición!de!HttpClient.put()!es!muy!parecida!a!la!anterior,!salvo!por!el!hecho!de!
que,!en!vez!de!crear!recursos,!se!utiliza!para!modificar!o!actualizar!la!información!de!un!
recurso!ya!existente.!
this.http.put<Object>(url, object, httpOptions);
!
Comparte! las! características!mencionadas! anteriormente! en! la! llamada! POST,! a!
excepción!de!la!idempotencia.!En!este!caso!las!peticiones!PUT!sí!que!son!idempontentes,!
es!decir,!no! importa! las!veces!que!se!ejecute!una!petición!PUT,!el! resultado!siempre!
debe!ser!el!mismo.!
2.10.1.4.! PETICIÓN DELETE
En!este!caso,!las!peticiones!HttpClient.delete()!se!utilizan!para!eliminar!recursos!del!
servidor.!También! se! considera!una!operación! idempontente!ya!que! la!aplicación!no!
espera!un!resultado!de!esta!petición.!!
this.http.delete<Object>(url, object, httpOptions);
!
Aunque! no! devuelva! un! resultado,! la! operación! debe! suscribirse! igualmente! al!
método! .subscribe()! ya! que! es! el! encargado! de! ejecutar! el! observable,! que! es!
precisamente!quien!inicia!la!petición!de!borrado.!
Los!métodos!HttpClient!no!inician!las!peticiónes!HTTP!hasta!que!se!llama!al!método!
subscribe()!en!el!observable!devuelto,!éste!es!el!encargado!de! lanzar! la!ejecución!de!
dicho! observable,! lo! que! provoca! que! HttpClient! componga! y! envíe! la! petición! al!
servidor.!
2.10.1.5.!AÑADIR CABECERAS
Algunas! peticiones! requieren! enviar! información! adicional! al! servidor! en! sus!
cabeceras,!para!realizar!operaciones!más!seguras!por!ejemplo,!enviando!un!token!de!autorización.!
La! implementación! de! dichas! cabeceras! se! realizará! en! el! objeto! httpOptions!
definiendo! la! propiedad! headers! que! será! de! tipo! HttpHeaders! incluido! en!
@angular/common/http.!!
import { HttpHeaders } from '@angular/common/http'; const httpOptions = { headers: new HttpHeaders({ 'Content-Type': 'application/json',
! Comparativa*entre*Angular*y*AngularJS.*Evolución*a*Angular*5.!
Angela!Serrano!Sánchez!! ! Página!73!!
'Authorization': 'my-auth-token' }) };
!
La! utilización! del! objeto! httpOptions! fue! mencionada! anteriormente! en! las!
peticiones!de!POST!y!PUT,!aunque!puede!enviarse!en!cualquier!método!de!HttpClient.!
2.10.2.! TRATAMIENTO DE LOS ERRORES
Puede!darse!la!situación!de!que!la!petición!que!se!envía!al!servidor!falla,!bien!por!
eventos! ajenos! al! ámbito! de! la! aplicación;! como!una!mala! conexión! a! internet! o! un!
bloqueo!en!el!servidor,!bien!porque!la!petición!llega!al!servidor,!pero!no!se!encuentra!el!
recurso!solicitado.!
En!estos!casos!HttpClient!devolverá!un!objeto!de!error!que!habrá!que!tratar!para!
dar!feedback!al!usuario!sobre!el!problema!ocurrido.!Esto!se!hace!añadiendo!un!segundo!
elemento!al!método!.subscribe()!
this.http.get<Object>(url).subscribe( (data: Object) => this.result = {data} error => this.error = error )
!
Los! errores! que! se! producen! por! causas! ajenas! a! la! aplicación! son! del! tipo!
ErrorEvent! de! JavaScript,! los! otros! son! errores! de! respuesta.! Ambos! tipos! son!
capturados! en! el! objeto!HttpErrorResponse.! Accediendo! al! error! de! la! respuesta,! se!
puede!evaluar!el!tipo!de!error!producido!y!actuar!en!consecuencia.!!
Cuando!el!error!producido!es!debido!a!una!causa!puntual,!podría!reintentarse!la!
petición!para!que! la!aplicación!pueda!seguir! funcionando!con!normalidad.!La!función!
retry()!de!la!librería!RxJS!aporta!esta!funcionalidad,!suscribiéndose!automáticamente!al!
observable!de!la!petición!fallida!un!cierto!número!de!veces.!
2.10.3.! INTERCEPTAR PETICIONES Y RESPUESTAS
Los! interceptores! son! una! de! las! características!más! importantes! que! aporta! la!
librería! @angular/common/http.! Como! bien! indica! el! nombre,! se! utilizan! para!
interceptar!peticiones!o!respuestas!del!servidor.!Son!capaces!de!recoger!esos!datos!y!
manipularlos!antes!de!que!lleguen!a!su!destino.!Por!ejemplo!son!útiles!cuando!hay!que!
añadir! cabeceras! a! las! peticiónes,! para! asignar! los! permisos! de! CORS! (CrossFOrigin*Resource*Sharing)!o!para!enviar!el!token!de!autenticación.!
!
! [UPM]!Máster*en*Ingeniería*Web!
Página!74!
Se! implementan! como! un! servicio! más,! aunque! debe! extender! la! interfaz!
HttpIntercept!y!sobrescribir!el!método!intercept()!en!función!de!las!necesidades!de!las!
peticiones!o!respuestas!que!se!intercepten;!
intercept(request: HttpRequest<any>, next: HttpHandler): return next.handle(request); }
Al!igual!que!otros!servicios,!debe!proporcionarse!la!clase!del!interceptor!antes!de!
que!la!aplicación!pueda!usarlo,!por!lo!que!puede!proveerse!en!el!módulo!principal.!
!
{ provide: HTTP_INTERCEPTORS, useClass: NoopInterceptor, multi: true }
!
Esta! configuración! obligatoria! le! dice! a! Angular! que!HTTP_INTERCEPTORS! es! un!
token!para!un!multiproveedor!que!inyecta!una!matriz!de!valores,!en!lugar!de!un!solo!
valor.!
Por!último!indicar!que,!aunque!los!interceptores!son!capaces!de!mutar!solicitudes!
y!respuestas,!las!propiedades!de!las!instancias!HttpRequest!y!HttpResponse!son!de!solo!
lectura,!lo!que!las!hace!inmutables.!Esto!es!así!por!una!buena!razón:!la!aplicación!puede!
volver!a!intentar!una!solicitud!varias!veces!antes!de!que!tenga!éxito,!lo!que!significa!que!
la!cadena!del!interceptor!puede!volver!a!procesar!la!misma!solicitud!varias!veces.!Si!un!
interceptor!puede!modificar!el!objeto!de!solicitud!original,!la!operación!reintentada!se!
iniciará! a! partir! de! la! solicitud! modificada! en! lugar! de! la! original.! La! inmutabilidad!
asegura!que!los!interceptores!vean!la!misma!solicitud!para!cada!intento.!
Si!aún!así!por!algún!motivo!es!necesario!modificar!una!petición,!se!debe!clonar!la!
petición! original! y! enviar! a! la! cadena! de! interceptores! el! elemento! clonado! para! no!
modificar!la!original.!
! !
! Comparativa*entre*Angular*y*AngularJS.*Evolución*a*Angular*5.!
Angela!Serrano!Sánchez!! ! Página!75!!
3.! ANGULAR VS ANGULARJS
Llegado! este! punto,! ya! se! han! estudiado! en! detalle! todos! los! elementos! que!
componen!el!nuevo!framework!Angular.!!Siguiendo!la!estructura!del!apartado!anterior,!se!pretende!realizar!una!comparativa!
entre!Angular!y!su!predecesor!AngularJS.!!
Así!mismo,!para!comprender!mejor!las!similitudes!y!diferencias!entre!ambos,!a!lo!
largo!de!los!siguientes!apartados!la!comparativa!se!apoyará!en!elementos!prácticos!de!
código! desarrollados! en! la! aplicación! SpotifyAngular,! para! aprender! a! utilizar! los!
distintos! elementos! de! Angular,! desde! su! instalación! y! puesta! en! marcha! hasta! la!
demostración!de!su!funcionamiento.!
3.1.! LA APLICACIÓN. SPOTIFYANGULAR.
Antes!de!entrar!a!comparar! los! frameworks!de!Angular!y!AngularJS,!ya!que!va!a!haber! referencias! constantes!a! la! aplicación!desarrollada,!es!necesario! ! introducir! su!
definición!y!funcionalidad.!
Para!la!implementación!funcional!de!una!aplicación!con!Angular,!se!ha!hecho!uso!
de!la!API7!de!Spotify,!que!proporciona!un!amplio!catálogo!de!operaciones!a!través!de!su!
endpoint!y!que!hará!las!veces!de!parte!backFend!de!la!aplicación.!La!aplicación!desarrollada!pretende!ser!un!gestor!de!listas!de!reproducción!propias!
de!un!usuario!con!cuenta!de!Spotify.!En!la!imagen!se!muestra!un!diagrama!de!casos!de!
uso!que!representa!la!funcionalidad!de!la!aplicación.!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!7!API!de!Spotify!https://developer.spotify.com/documentation/weboapi/reference/!!
! [UPM]!Máster*en*Ingeniería*Web!
Página!76!
!Imagen*13.*Diagrama*de*casos*de*uso*de*SpotifyAngular*
!
La! gran!mayoría! de! peticiones! a! la! API! de! Spotify! requieren! que! se! envíe! en! la!
cabecera!un!Token!de!autenticación.!Para!obtener!este!token,!como!prerrequisito,!el!
usuario!debe!tener!una!cuenta!activa!de!Spotify!y!un!código!de!Client!ID,!que!se!puede!
obtener!desde!la!página!web!para!desarrolladores!de!Spotify8.!Con!este!código,!se!ha!
implementado! el! flujo! de! autorización! implícita! de! OAuth9! de! forma! que,! desde! la!
primera!pantalla!de! la!aplicación!el!usuario!pueda!entrar!al! resto!de! funcionalidades!
simplemente!pulsando!el!botón!de!‘Sign!In’.!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!8!Spotify!Developers!https://developer.spotify.com/dashboard/applications!!9!OAuth!(Open!Authorization)!es!un!estándar!abierto!que!permite!flujos!simples!de!autorización!para!sitios!web!o!aplicaciones!informáticas.!
! Comparativa*entre*Angular*y*AngularJS.*Evolución*a*Angular*5.!
Angela!Serrano!Sánchez!! ! Página!77!!
!Imagen*14.*Pantalla*de*Log*In*de*SpotifyAngular*
Una!vez!dentro,!el!usuario!verá!un!mensaje!de!bienvenida!y!en!la!cabecera!de!la!
aplicación!una!barra!de!navegación!con!diferentes!opciones,!entre!ellas!navegar!a!su!
perfil!del!usuario,!escoger!una!de!sus!playlist!o!crear!una!nueva!desde!el!combo,!e!iniciar!
una!búsqueda!en! Spotify! por!Artista,! Álbum!o!Canción,! aunque! si! no! se! indica! nada!
buscará!todas!las!opciones!por!defecto.!
!
!Imagen*15.*Página*de*inicio*de*SpotifyAngular*
A!partir!de!aquí,!el!usuario!podrá!acceder!a!distintas!partes!de!la!aplicación.!Por!
ejemplo!si!pulsa!en!su!perfil!de!usuario!en! la!barra!de!navegación,! se!mostráran!sus!
datos!del!perfil!y!el!botón!‘following’,!a!través!del!cual!podrá!consultar!los!artistas!a!los!
que!sigue.!Será!desde!esta!misma!parte!de!la!aplicación!desde!donde!el!usuario!podrá!
dejar!de!seguir!a!los!artistas!que!sigue!actualmente.!
! [UPM]!Máster*en*Ingeniería*Web!
Página!78!
!Imagen*16.*Página*de*perfil*del*usuario*
Desde!el!combo!de!playlist!el!usuario!podrá!acceder!a!cualquiera!de!sus!playlist!
públicas!ó!crear!una!nueva.!Desde!la!lista!de!canciones!que!se!muestran!en!una!playlist!
concreta,!el!usuario!podrá!eliminar!o!escuchar!la!canción.!
!
!Imagen*17.*Página*con*vista*de*playlist*y*popFup*de*creación*de*playlist*
En!el!formulario!de!búsqueda!en!la!parte!lateral!derecha!de!la!barra!de!navegación,!
se!podrán!realizar!búsquedas!filtrando!por!artista,!álbum,!canción!o!todos.!En!caso!de!
que!se!realice!la!búsqueda!filtrando!por!todos!los!elementos,!en!la!pantalla!se!mostráran!
los!resultados!de!canciones,!artistas!y!álbumes!coincidentes!hasta!un!máximo!de!cinco!
por!categoría.!
!
! Comparativa*entre*Angular*y*AngularJS.*Evolución*a*Angular*5.!
Angela!Serrano!Sánchez!! ! Página!79!!
!Imagen*18.*Página*con*resultados*de*la*búsqueda*
La!navegabilidad!está!presente!en!toda! la! funcionalidad!de! la!web.!Siempre!que!
aparezca!una!canción!en!la!pantalla,!el!usuario!podrá!añadir!esa!canción!a!cualquiera!de!
sus!listas!o!navegar!tanto!a!la!página!del!artista!o!artistas,!como!a!la!página!del!álbum!
correspondiente.!En!el!caso!de!encontrase!en!la!página!de!un!artista,!se!podrá!navegar!
a!cualquiera!de!sus!álbum.!
En!esta!aplicación!han!intentado!aplicarse!todos,!o!casi!todos!los!elementos!vistos!
en!el!apartado!anterior!de!Angular,!en!los!siguientes!apartados!se!tratarán!de!ver!cada!
uno!de!ellos!independientemente,!aplicando!a!su!vez!una!comparativa!con!AngularJS.!
3.2.! INSTALACIÓN
Ya!que!la!comparativa!va!a!llevarse!a!cabo!en!términos!más!prácticos,!habría!que!
comenzar!por!estudiar! las!diferencias!que!existen!a! la!hora!de!poner!un!proyecto!en!
marcha.!La!instalación!es!uno!de!los!puntos!en!los!que!más!difieren!ambos!frameworks.!Mientras!que!las!primeras!versiones!de!AngularJS!se!instalaban,!bien!descargando!
un! fichero! con! las! fuentes! del! framework,! bien!mediante! CDN! para! posteriormente!
referenciarlo! dentro! la! sección! <header>! del! fichero! .html! principal! de! la! aplicación,!
Angular! dispone! de! una! interfaz! por! línea! de! comandos! que! permite! crear!
automáticamente!la!estructura!de!un!proyectos.!
3.2.1.! ANGULAR CLI
Angular!CLI!es!una!herramienta!para! inicializar,!desarrollar,!crear! la!estructura!y!
mantener! fácilmente! aplicaciones! Angular,! es! decir,! lleva! a! cabo! el! scaffolding! de! la!aplicación.!!
! [UPM]!Máster*en*Ingeniería*Web!
Página!80!
Como!prerrequisitos!deben!instalarse!previamente!Node.js!y!npm.!Una!vez!están!
disponibles! en! la! máquina! para! instalar! Angular! CLI! de! forma! global! se! ejecuta! el!
siguiente!comando;!
!npm install -g @angular/cli
Angular! CLI! proporciona! una! serie! de! comandos! que! facilitan! la! creación! de!
proyectos,!así!como!la!generación!de!los!distintos!elementos!de!la!aplicación,! incluso!
arranca!la!aplicación!en!un!servidor.!!
La!ejecución!del!comando!ng!en! la!ventana!del! terminal!de! la!máquina!muestra!
información!sobre!todos!los!comandos!disponibles,!como!se!muestra!en!la!Imagen!19.!
!
!Imagen*19.*Comandos*de*Angular*CLI*
De!entre!todos! los!comandos!anteriores!cabe!destacar!el!comando!ng!new,!que!
sirve!para!crear!un!nuevo!proyecto!Angular.!
!ng new [nombreDelProyecto]
El!comando!ng!generate!permite!crear!nuevos!elementos!dentro!de!la!aplicación!
como!componentes,!directivas,!servicios,!filtros,!etc.!
!
! Comparativa*entre*Angular*y*AngularJS.*Evolución*a*Angular*5.!
Angela!Serrano!Sánchez!! ! Página!81!!
!Imagen*20.*Creación*de*elementos*con*Angular*CLI*
Y!se!aplicaría!de!la!siguiente!manera;! ng generate <schematic> [name] (options)
!
Donde!generate!podría!sustituirse!simplemente!por!una!g!(goenerate),!<schematic>!
sería!el!tipo!de!elemento!a!crear,!que!podría!ser!cualquiera!de!las!opciones!mostradas!
en!la! imagen!anterior,![name]!sería!el!nombre!que!recibe!dicho!elemento!y!(options)!
podría!ser!cualquier!opción!disponible!para!el!elemento!especificado.!
Por! último! ng! serve,! sería! el! comando! encargado! de! construir! la! aplicación! y!
arrancar!un!servidor!para!su!ejecución.!
!ng serve (options)
Normalmente!la!ruta!de!ejecución!por!defecto!será!http://localhost:4200/.!
3.2.2.! ARQUITECTURA
La!arquitectura!puede!que!sea!uno!de!los!puntos!en!los!que!más!difieren!ambos!
frameworks,! precisamente! la! reestructuración! de! Angular! surge! para! solventar! las!
carencias!encontradas!en!AngularJS,!muchas!de!ellas!debidas!a!su!arquitectura.!
Mientras! que! en! la! arquitectura! de! Angular! los! elementos! principales! son! los!
módulos!y! los!componentes,! la!arquitectura!de!AngularJS!se!estructura!con!el!patrón!
MVW(ModelFViewFWhatever)!tal!y!como!lo!denominan!sus!creadores.!
Ya!que! la! arquitectura!de!Angular!ha! sido!ampliamente!definida!en!el! apartado!
anterior,! es! conveniente! definir! en! este! punto! la! arquitectura! de! AngularJS! para!
comprender!mejor!la!diferencia.!
! [UPM]!Máster*en*Ingeniería*Web!
Página!82!
3.2.2.1.! ARQUITECTURA DE ANGULARJS
Siguiendo!la! línea!de! los! framworks!existentes!para!el!backFend,!AngularJS!surge!para!estructurar!el!código!en! la!parte!del!cliente,!es!decir,!para!estructurar!el!código!
JavaScript,!CSS!y!HTML.!A!medida!que!las!responsabilidades!de!la!implementación!del!
frontFend!crecen,!es!necesario!separar!esas!responsabilidades!del!mismo!modo!que!en!
el!back,!con!un!patrón!de!arquitectura!software.!Echando!un!primer!vistazo!al!framework,!podría!entenderse!que!AngularJS!sigue!la!
estructura! del! patrón! MVC(ModelFViewFController),! aunque! lo! cierto! es! que! las!necesidades!del!framework!no!se!ajusta!del!todo!a!lo!que!este!patrón!especifica,!ya!que!la!arquitectura!de!AngularJS!no!se!ciñe!únicamente!a!vistas,!controladores!y!el!modelo.!
Para!dar!aclaración!al!tipo!de!patrón!arquitectónico!que!sigue!este!framework,!los!
autores!declararon!que!AngularJS!sigue!el!patrón!ModelFViewFWhatever!(MVW).!!
!“Durante*varios*años*AngularJS*estuvo*más*cerca*del*patrón*MVC*(o*más*bien*una*de*sus*
variantes*del*lado*del*cliente),*pero*con*el*tiempo*y*gracias*a*muchas*refactorizaciones*y*mejoras*de* la*API,*ahora*está*más*cerca*del*patrón*MVVM(ModelFViewFViewModel):*el*objeto*$scope*podría*considerarse*el*ViewModel,*decorado*por*una*función*que*llamamos*Controlador.*
Ser*capaz*de*categorizar*un*framework*y*ponerlo*en*uno*de*los*patrones*MV***tiene*algunas*ventajas.*Puede*ayudar*a*los*desarrolladores*a*sentirse*más*cómodos*con*sus*apis*al*facilitar*la*creación*de*un*modelo*mental*que*represente*la*aplicación*que*se*está*creando*con*el*framwork.*También*puede*ayudar*a*establecer*la*terminología*utilizada*por*los*desarrolladores.*
Dicho* esto,* preferiría* que* los* desarrolladores* construyan* aplicaciones* * que* estén* bien*diseñadas*y*sigan*la*separación*de*responsabilidades,*que*verles*perder*el*tiempo*discutiendo*sobre*tonterías*de*MV**.*Y*por*esta*razón,*por*la*presente*declaro*que*AngularJS*es*un*framework*MVW*F*ModelFViewFWhatever.*Donde*Whatever*representa*"lo*que*sea*que*funcione*para*ti".*
Angular*brinda*mucha*flexibilidad*para*separar*bien*la*lógica*de*presentación*de*la*lógica*de*negocio*y*el*estado*de*la*presentación.*Úselo*para*alimentar*su*productividad*y*el*mantenimiento*de*la*aplicación*en*lugar*de*discusiones*acaloradas*sobre*cosas*que*al*final*del*día*no*importan*tanto.”* * * * * * * * * * * ** * * * * Igor*Minar,*AngularJS*contributor*(Minar,*2012)*
3.2.2.2.! ESTRUCTURA DE UN PROYECTO ANGULAR VS
ANGULARJS
En!un!enfoque!más!práctico,!una!de!las!grandes!ventajas!de!Angular!es!que!a!través!
de!Angular! CLI,! simplemente! con!ejecutar! un! comando!el! scaffolding! genera! toda! la!estructura!de!archivos!y!carpetas!necesarios!para!poner!en!marcha!un!proyecto.!
En!concreto,!se!genera!la!siguiente!estructura;!
!
! Comparativa*entre*Angular*y*AngularJS.*Evolución*a*Angular*5.!
Angela!Serrano!Sánchez!! ! Página!83!!
!Imagen*21.*Estructura*de*un*proyecto*Angular*
En! esta! estructura,! la! carpeta! node_modules! contiene! las! dependencias! del!
proyecto,!como!las!librerías!@angular/router!o!@angular/http,!etc.!
Aunque!puede!que!los!ficheros!más!importantes!sean!el!fichero!de!configuración!
de!angular!CLI!(angular.json),!main.js,!index.html!y!las!fuentes!contenidas!en!la!carpeta!
src/app.! Estos! ficheros! son! el! módulo! y! el! componente! principal! que! se! generan!
automáticamente!al!crear!un!proyecto!con!ng!new.!
Cada!uno!de!estos!elementos!participa!en!la!decisión!de!cómo!va!a!ejecutarse!la!
aplicación.!El!fichero!angular.json!indica!cual!va!a!ser!el!punto!de!entrada!a!la!aplicación.!
!
! [UPM]!Máster*en*Ingeniería*Web!
Página!84!
!Imagen*22.*Fichero*de*configuración*angular.json*
Cuando!se!arranque!el!servidor,!será!el!fichero!main.ts!el!primero!en!ejecutarse.!
Este!fichero!se!encarga!de,!además!de!compilar!la!aplicación,!cargar!el!módulo!principal!
AppModule! contendio! en! app/app.module.ts! para! que! se! ejecute! en! el! navegador.!
Cuando!el!módulo!principal! ya!está!cargado,! los!metadatos!generados! indicarán!qué!
componente! será! el! primero! en! ejecutarse,! que! siguiendo! con! la! nomenclatura! que!
aplica!angular!será!el!componente!AppComponent!app/app.component.ts.!!
Se! carga! entonces! la! vista! principal! index.html! que! contiene! la! directiva! con! la!
referencia!al!componente!principal!por!el!nombre!de!su!selector.!
!
!Imagen*23.*Puesta*en*marcha*de*un*proyecto*Angular*
A!partir!de!aquí!es!decisión!del!desarrollador!elegir!cómo!va!a!estructurar!dentro!
de!la!carpeta!de!las!fuentes!los!elementos!creados.!
En!!AngularJS!todo!el!proceso!de!configuración!es!manual,!no!hay!herramientas!que!
generen!la!estructura!automáticamente.!En!este!caso!el!equipo!de!desarrolladores!de!
AngularJS!pone!a!disposición!de! los!programadores,!a!través!de!su!cuenta!de!GitHub!
! Comparativa*entre*Angular*y*AngularJS.*Evolución*a*Angular*5.!
Angela!Serrano!Sánchez!! ! Página!85!!
oficial! un! proyecto! llamado! angularoseed10,! que! no! es!más! que! el! esqueleto! de! una!
aplicación!para!poder!comenzar!a!desarrollar!un!proyecto!en!Angular!JS.!!
En!la!aplicación!de!SpotifyAngular,!las!fuentes!del!proyecto!se!subdividen!en!tres!
carpetas! según! la! funcionalidad! de! los! elementos! que! las! conforman;! estas! son!
componentes,!servicios!y!modelos!como!se!muestra!en!la!siguiente!imagen.!
!
!Imagen*24.*Organización*del*proyecto*SpotifyAngular*
En!el!caso!de!AngularJS!podría!organizarse!de!forma!parecida,!en!el!apartado!de!
componentes!de!esta!comparativa!se!verá!que!AngularJS!proporciona!una!forma!similar!
de! relacionar! controladores! y! plantillas! en! lo! que! se! denomina! también! como!
componente,!de!forma!similar!a!como!se!estructuran!los!componentes!de!Angular.!Pasa!
lo!mismo!con!los!servicios!en!este!caso,!ambos!frameworks!comparten!puntos!en!común!
a!la!hora!de!definir!estos!elementos.!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!10!Proyecto!con!el!esqueleto!de!una!aplicación!Angularjs!https://github.com/angular/angularoseed!
! [UPM]!Máster*en*Ingeniería*Web!
Página!86!
No! será! así! para! los! modelos,! ya! que! esta! carpeta! contiene! clases! de! objetos!
definidas! con! atributos! tipados,! que! es! una! de! las! ventajas! que! presenta! TypeScript!
frente!a!JavaScript.!
De!hecho,!antes!de!que!se!empezasen!a!utilizar!los!componentes!en!AngularJS!los!
proyecto!solían!organizarse!en!controladores,!servicios!y!vistas!de!forma!independiente,!
como!el!ejemplo!que!se!muestra!en!la!imagen!siguente.!
*
Imagen*25.*Estructura*de*un*proyecto*AngularJS*
Antes!de!seguir!con!la!comparativa,!es!necesario!saber!cómo!poner!en!marcha!la!
aplicación! SpotifyAngular! desarrollada!para! apoyar! los! ejemplos! que! se! verán! en! los!
siguientes!puntos!de! la!memoria.!Antes!de! arrancar! el! servidor,! deben! instalarse! las!
dependencias!del!proyecto.!Para!ello!desde!la!carpeta!root!de!la!aplicación,!donde!se!encuentra!el!fichero!de!configuración!angular.json,!se!ejecuta!el!siguiente!comando;!
!npm install!
!
Una! vez! que! el! proyecto! se! ha! instalado! correctamente! ya! puede! ejecutarse! la!
aplicación!con!ng!serve,!como!se!ha!visto!en!el!apartado!anterior.!
! Comparativa*entre*Angular*y*AngularJS.*Evolución*a*Angular*5.!
Angela!Serrano!Sánchez!! ! Página!87!!
3.2.3.! MÓDULOS
El! concepto!de!módulo!es!bastante! similar!en!ambos! framework.!El!objetivo!de!
crear! módulos! en! las! aplicaciones! es! agrupar! elementos! cuya! funcionalidad! está!
relacionada,! además! ambos! comparten! la! premisa! de! que,! al! encapsular! la!
funcionalidad,! los!módulos!pueden!ser! reutilizados!en!otras!partes!de! la!aplicación!e!
incluso!en!otros!proyectos.!
Hasta!aquí!el!parecido.!!
En! Angular! la! creación! de! un! módulo! se! realiza! indicando! en! el! decorador!
@NgModule!todos!los!elementos!que!va!a!necesitar!ese!módulo!para!que!éste!pueda!
funcionar!correctamente!y!todos!sus!elementos!puedan!comunicarse!y!colaborar!entre!
sí.!Es!decir,!en!los!metadatos!se!indicarán!módulos,!componentes,!directivas,!servicios,!
así!como!cualquier!otro!elemento!creado!que!el!módulo!requiera.!
En!AngularJS!en!la!definición!de!un!módulos!sólo!podrán!indicarse!las!dependencias!
con!otros!módulos,!por! lo!que!se!vuelve!necesaria! la!definición!de!número!mayor!de!
módulos!en!el!desarrollo!de!!aplicaciones.!
Por!poner!un!ejemplo!más!claro,!se!usa!como!referencia!el!módulo!principal!de!la!
aplicación!SpotifyAngular;!
import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { HttpClientModule } from '@angular/common/http'; import { routingModule } from './app.routing'; {...} //Resto de imports para los elementos de NgModule
@NgModule({ declarations: [ AppComponent, CallbackComponent, SignInComponent, PlaylistsComponent, PlaylistDetailsComponent, AlbumsComponent, ArtistsComponent, CreatePlaylistComponent, HeaderComponent, AlbumDetailsComponent, UserComponent, FollowingComponent, ReplaceAmpPipe, SearchResultsComponent, FollowingDirective, ], imports: [ BrowserModule, HttpClientModule, MaterialModule,
! [UPM]!Máster*en*Ingeniería*Web!
Página!88!
BrowserModule, BrowserAnimationsModule, FormsModule, ReactiveFormsModule, UserRoutingModule, routingModule ], providers: [ SpotifyLoginService, SpotifyProfileService, SpotifyPlaylistService, SpotifyFollowService, { provide: LocationStrategy, useClass: PathLocationStrategy }, { provide: HTTP_INTERCEPTORS, useClass: TokenInterceptor, multi: true } ], entryComponents: [PlaylistsComponent, CreatePlaylistComponent], bootstrap: [AppComponent] }) export class AppModule { }
!
En!este!módulo!se!ven!los!distintos!elemento!que!componen!los!metadatos!de!la!
directiva!@NgModule;!en!el!array!de!declarations!se! incluyen! los!componentes!de! la!
aplicación,! en! el! de! imports! otros!módulos,! bien! contenidos! en! la! propia! aplicación!
(como!es!el!caso!de!MaterialModule),!bien!contenidos!en!otras!librerías!de!Angular,!y!
por!último!el!array!de!providers!que!contiene!los!servicios!declarados!globalmente.!
En!AngularJS!el!módulo!principal,!sólo!contendría!la!declaración!de!otros!módulos!
ya!que!la!forma!de!cargar!módulos!en!AngularJS!es!(Google,!AngularJS,!2018);!
!angular.module('AppModule', [])
!
Dónde!myModule,!es!el!nombre!que!se!asigna!al!módulo,!lo!que!sería!equivalente!
al!“export!class!AppModule”!del!módulo!anterior!y!!dónde!el!segundo!parámetro!es!un!
array!que!puede!incluir!únicamente!otros!módulos.!
Una!forma!de!especificar!el!módulo!de!la!aplicación!SpotifyAngular!en!AngularJS!
podría!ser!la!siguiente;!
angular.module(‘AppModule’, [ ‘BrowserModule’, ‘HttpClientModule’, ‘BrowserModule’,
! Comparativa*entre*Angular*y*AngularJS.*Evolución*a*Angular*5.!
Angela!Serrano!Sánchez!! ! Página!89!!
‘BrowserAnimationsModule’, ‘FormsModule’, ‘ReactiveFormsModule’, ‘UserRoutingModule’, ‘routingModule’ ]);
!
Para! el! resto! de! elementos,! habría! que! tomar! decisiones! arquitectónicas! y!
subdividirlos!en!varios!grupos,!basados!por!ejemplo!en!funcionalidad!y!para!cada!grupo!
declarar!un!nuevo!módulo!que!pueda! incluirse!después!en!el!módulo!principal!de!al!
aplicación.!Más! adelante,! se! verá! como! se! especifica! individualmente! dentro! de! un!
módulo!cada!tipo!de!elemento!de!la!configuración!del!ejemplo.!
En!general! las!pautas!que! recomienda! la!documentación!oficial!de!Angular!para!
crear!módulos!son!las!siguientes;!
•! Un!módulo!para!cada!funcionalidad.!•! Un! módulo! para! cada! componente! reutilizable! (especialmente! directivas! y!
filtros).!•! Y! un! módulo! principal! que! depende! de! los! módulos! anteriores! y! contiene!
cualquier!código!de!inicialización.!
La!forma!de!declarar!los!módulos!en!AngularJS!es!importante!y!deben!ordenarse!
según!unas!preferencias!concretas!ya!que,!al!ejecutarse!la!aplicación!AngularJS!primero!
se!cargan!los!providers!o!proveedores!y!los!servicios!que!proveen,!después!los!bloques!de!configuración!del!módulo!requerido!y!esto!escala!hasta!que!se!resuelven!todas!las!
dependencias!del!resto!de!módulos.!
Volviendo!al!ejemplo!del!módulo!principal!de!SpotifyAngular,!se!aprecia!que!en!el!
array!de!providers,!se!ha!incluido;!
{ provide: LocationStrategy,
useClass: PathLocationStrategy } !
Angular! proporciona! dos! estrategias! de! composición! de! rutas,! dependiendo! del!
navegador!que!se!utilice;!las!rutas!hash!y!las!rutas!html5.!
Como! se! ha! comentado! anteriormente! en! esta! guía! los! navegadores!modernos!
usan! la! técnica! HTML5! pushState,! que! es! la! estrategia! que! implementa! Angular! por!
defecto,! y!que!es!precisamente! la!que! referencia! la! clase!PathLocationStrategy.!Para!
usar!la!estrategia!de!rutas!tipo!hash!se!utilizaría!la!clase!HashLocationStrategy.!
Aunque!en!este!ejemplo!no!sería!necesario!indicar!que!la!!estrategia!que!sigue!la!
aplicación!es!la!de!HTML5,!sirve!para!comparar!cómo!se!define!en!la!configuración!de!
un!módulo!AngularJS,! ya!que!en!este! framework! si! suele! ser!necesario!especificar! la!
técnica!de!rutas.!Siguiendo!con!la!transformación!del!código!Angular!de!SpotifyAngular;!
! [UPM]!Máster*en*Ingeniería*Web!
Página!90!
angular.module(‘AppModule’).config(function($locationProvider) { $locationProvider.html5Mode(true); })
!
Se! inyecta! en! la! función! del! bloque! de! configuración! el! proveedor!
$locationProvider,!que!es!el!equivalente!al!proveedor!Angular,!LocationStrategy.!En!el!
caso!de!querer!utilizar!la!estrategia!hash,!habría!que!utilizar!el!método!.hashPrefix().!
3.2.4.! COMPONENTES
El!peso!de!la!lógica!de!una!aplicación!AngularJS!solía!recaer!en!los!controladores.!
En!sus!inicios!su!arquitectura!se!asemejaba!más!al!patrón!MVC!por!el!hecho!de!que!la!
aplicación!se!estructura!en!controladores!que!manejan!la!lógica!de!negocio,!delegan!el!
acceso!a!los!datos!en!las!peticiones!al!servidor!y!devuelven!los!resultados!a!la!vista.!Es!
esta!última!quien!se!encarga!de!mostrar!los!datos!al!usuario!a!través!de!una!interfaz.!
A!partir!de!la!versión!1.5!de!AngularJS,!que!se!libera!el!mismo!año!que!Angular!2,!
se!introduce!el!término!de!componente!en!el!framework.!El!concepto!es!prácticamente!
el!mismo,!un!elemento!que!sirve!para!desarrollar!aplicaciones!siguiendo!la!arquitectura!
basada!en!componentes!(Google,!AngularJS,!2018).!
La! definición! de! un! componente! en! Angular,! se! hace! a! través! de! la! anotación!
@Component! y! se! caracteriza! por! asociar! una! clase! a! una! vista! determinada.! En!
AngularJS!el!método!.component()!asociado!a!un!módulo!funciona!de!forma!similar,!en!
él!pueden!relacionarse!un!controlador!con!una!plantilla.!
Por!ejemplo!el!componente!albums.component.ts!que!recupera! información!del!
un!álbum!concreto!de!Spotify,!en!la!aplicación!desarrollada!se!implementa!como;!
import { Component, OnInit} from '@angular/core'; import { ActivatedRoute, ParamMap } from '@angular/router'; import { Album } from '../../models/albums'; import { Observable } from 'rxjs'; import { SpotifyAlbumsService } from '../../sevices/spotify-album/spotify-albums.service'; import { switchMap } from 'rxjs/operators'; @Component({ selector: 'app-albums', templateUrl: './albums.component.html', styleUrls: ['./albums.component.css'], providers: [ SpotifyAlbumsService ] }) export class AlbumsComponent implements OnInit { album$: Observable<Album>; constructor(private activatedRoute: ActivatedRoute,
! Comparativa*entre*Angular*y*AngularJS.*Evolución*a*Angular*5.!
Angela!Serrano!Sánchez!! ! Página!91!!
private spotifyAlbums: SpotifyAlbumsService) { } ngOnInit() { this.album$ = this.activatedRoute.paramMap.pipe( switchMap((params: ParamMap) => this.spotifyAlbums.getAlbumById(params.get('id'))) ); } }
!
En!AngularJS!quedaría!como;!
angular.module('appModule', []) .component('albums', { controller: ['$routeParams', ‘SpotifyAlbum’, function AlbumsController('$scope','$routeParams', albumService) { var self = this; self.$onInit = function () { self.album = SpotifyAlbum.getAlbumById({id: $routeParams.id}); }; }], templateUrl: 'albums.html' })
!
En! este! ejemplo! el! componente!de!AngularJS! contendría! la! plantilla! asociada! al!
controlador! ‘albums’.! A! este! controlador! se! le! inyecta! el! servicio! ‘albumService’! del!
mismo! modo! que! en! Angular! se! inyecta! el! servicio! SpotifyAlbumService! en! su!
constructor.! Este! servicio! es! el! encargado! de! hacer! las! peticiones! al! servidor!
relacionadas!con!los!datos!de!los!álbumes.!!
También!se!le!inyecta!el!proveedor!$routeParams!para!recuperar!el!id!del!álbum!
seleccionado,!equivalente!a! la! clase!ActivatedRoute!de!Angular,! cuya!comparativa! se!
verá!en!detalle!en!el!apartado!de!Navegación!y!Routing.!
3.2.4.1.! CICLOS DE VIDA DEL COMPONENTE
Como!puede!verse!en!el!ejemplo!anterior,!el!componente!de!AngularJS!también!
dispone!de!métodos!que!controlan!el!ciclo!de!vida!del!componente.!Son!los!mismos!que!
en!Angular,!porque!la!implementación!del!componente!en!AngularJS!se!introdujo!con!
las!mismas!características!que!las!de!los!componentes!Angular.!
! [UPM]!Máster*en*Ingeniería*Web!
Página!92!
3.2.4.2.! PLANTILLAS Y DATA BINDING
En!este!caso!fue!AngularJS!y!no!Angular!quien!introdujo!el!término!de!data*binding.!Esta!técnica!consiguió!desvincular!la!lógica!del!controlador!de!los!datos!que!finalmente!
se!muestran!en!la!vista.!
Lo!consiguió!utilizando!en!las!plantillas!el!lenguaje!HTML,!combinado!con!etiquetas!
propias! de! AngularJS.! Esto,! junto! con! la! directivas! son! quizás! el! principal! legado! de!
AngularJS!al!Angular!actual.!
Se! aplican! a! la! plantilla! los!mismos! elementos! que! ya! se! han! visto! en! Angular:!
directivas,! filtros! (conocidos! como!Pipes! en!Angular),! la! interpolación! y! controles! de!
formularios.!
Por!ejemplo,!siguiendo!con!la!plantilla!asociada!al!componente!de!albums!anterior,!
su!plantilla!es;!
<app-header></app-header> <span *ngIf="album$ | async as album"> <app-album-details [album]="album"></app-album-details> </span>
!
En!AngularJS!su!equivalente!sería;!
<app-header></app-header> <span ng-if="self.album"> <app-album-details album="self.album"></app-album-details> </span>
!
Finalmente,! la! visualización!de! la!plantilla! anterior! en! la! aplicación!muestra!una!
barra!de!navegación!contenida!en!el!componente!header.component.ts!!y!el!detalle!del!
álbum!seleccionado! (nombre!del!disco,! imagen!del!disco!y! canciones),! tal! y! como!se!
muestra!en!la!siguiente!imagen.!
! Comparativa*entre*Angular*y*AngularJS.*Evolución*a*Angular*5.!
Angela!Serrano!Sánchez!! ! Página!93!!
!Imagen*26.Vista*del*componente*albums.component.ts*
Realmente,! la!plantilla!anterior!no!contiene!muchos!elementos!para!realizar!una!
comparativa!más!o!menos!completa,!por!lo!que!se!muestra!a!continuación!otra!plantilla!
de! la! aplicación! SpotifyAngular! con! información! sobre! un! artista! contenida! en!
artist.component.html!que!se!implementa!como;!
<app-header></app-header> <div> <h1> </h1> <button (click)="followArtist()">Follow</button> </div> <table class="table table-hover table-sm" *ngIf="tracks"> <thead> <tr> <th scope="col">Song</th> <th scope="col">Album</th> <th scope="col">Time</th> <th scope="col">Play</th> <th scope="col">Add</th> </tr> </thead> <tbody> <tr *ngFor="let track of tracks"> <td colspan="2">{{track.name}}</td> <td colspan="2"><a [routerLink]="['/albums',
track.album.id]">{{track.album.name}}</a></td> <td colspan="2">{{track.duration_ms | date:’mm:ss’}}</td> <td colspan="2"><button
(click)="playTrack(track.preview_url)">Play</button></td>
! [UPM]!Máster*en*Ingeniería*Web!
Página!94!
<td> <button mat-button [matMenuTriggerFor]="menu">+</button>
<mat-menu #menu="matMenu"> <span *ngFor="let playlist of playlists?.items"> <button mat-menu-item
(click)="addToPlaylist(track.uri, playlist.id)">{{playlist.name}}</button>
</span> </mat-menu> </td> </tr> </tbody> </table> <div *ngIf="albums"> <app-album-details *ngFor="let album of albums.items"
[album]="album"> </app-album-details> </div> !
La!comparativa!con!AngularJS!podría!representarse!como;!
<app-header></app-header> <div> <h1> </h1> <button ng-click="followArtist()">Follow</button> </div> <table class="table table-hover table-sm" ng-if="tracks"> <thead> <tr> <th scope="col">Song</th> <th scope="col">Album</th> <th scope="col">Time</th> <th scope="col">Play</th> <th scope="col">Add</th> </tr> </thead> <tbody> <tr ng-repeat="track in tracks"> <td colspan="2">{{track.name}}</td> <td colspan="2"><a href="'/albums/{{track.album.id}}"> {{track.album.name}}</a></td> <td colspan="2">{{track.duration_ms | date:’mm:ss’}}</td> <td colspan="2"><button ng-click
="playTrack(track.preview_url)">Play</button></td>
// Elementos propios de Angular Materials // ***************************************
<td> <button mat-button [matMenuTriggerFor]="menu">+</button> <mat-menu #menu="matMenu">
! Comparativa*entre*Angular*y*AngularJS.*Evolución*a*Angular*5.!
Angela!Serrano!Sánchez!! ! Página!95!!
<span ng-repeat="playlist in playlists.items"> <button mat-menu-item ng-click="addToPlaylist(track.uri,
playlist.id)">{{playlist.name}}</button> </span> </mat-menu> </td> // *************************************** </tr> </tbody> </table> <div ng-if="albums"> <app-album-details ng-repeat="album in albums.items"> </app-album-details> </div> !
Obviando! los! elementos! propios! de!Angular!Materials,! los! cambios! son!pocos! y!
difíciles!de!apreciar;!sólo!cambian!las!directivas,!en!AngularJS!las!directivas!se!prefijan!
con!ngo!en!vez!de!*ng.!
3.2.5.! DIRECTIVAS
Las!directivas!son!los!elementos!más!importantes!en!la!arquitectura!del!framework!
AngularJS.! Tanto! es! así! que! se! compone! de! casi! setenta! directivas! predefinidas.! En!
Angular! en! cambio,! se! opta!más! por! que! sea! el! desarrollador! quien! implemente! las!
directivas!de!la!aplicación,!a!excepción!de!las!ya!mencionadas!en!este!informe.!
La! más! importante! en! AngularJS! es! ngoapp! que! realiza! el! bootstraping! de! la!
aplicación.!Suele!asociarse!a!un!elemento!de!la!plantilla,!generalmente!en!el!body;!
!<body ng-app="appModule">
En!Angular!no!existe!esta!directiva!ya!que,! tal!y!como!se!vió!en! la! instalación!el!
proceso!de!bootstraping!la!inicialización!del!módulo!principal!se!lleva!a!cabo!desde!la!
clase!main.ts.!
También!desaparece!la!directiva!ngocontroller,!ya!que!el!concepto!de!Controlador!
no! existe! como! tal! en! Angular,! en! su! lugar! el! decorador! @Component! de! la! clase!
especifica!la!plantilla!asociada.!
Algunas!como!click!o!blur!se!capturan!en!eventos!con!la!técnica!de!event*binding,*y!otras!como!href!o!src!usan!la!técnica!de!property!binding.!
Quedarían! algunas! como! las! que! se! han! visto! en! el! apartado! anterior,! en! las!
plantillas,!como!ngoif,!cuya!equivalente!es!*ngIf!o!ngorepeat,!que!sería!la!actual!*ngFor.!
En!el!caso!de!esta!última,!hay!una!diferencia!a! la!hora!de!iterar!y!es!que!*ngFor!
genera!una!variable!de!entrada!en!cada!iteración,!cosa!que!no!sucede!con!ngorepeat.!
! [UPM]!Máster*en*Ingeniería*Web!
Página!96!
Otras!directivas!como!ngoclass,!ngostyle,!ngoswitch!o!ngomodel!también!mantiente!
el! mismo! funcionamiento! con! sus! equivalentes! en! Angular! [ngClass],! [ngStyle],!
*ngSwitch!y![(ngModel)].!
En!el!caso!de!la!creación!de!directivas!personalizadas,!en!SpotifyAngular!se!define!
la!directiva!appFollowing.!Es!una!directiva!de!atributo!que!modifica!el!valor!de!un!botón!
en!función!de!si!el!usuario!sigue!o!no!a!un!artista;!!
@Directive({ selector: '[appFollowing]', }) export class FollowingDirective implements OnChanges, OnDestroy { @Input() id: string; subscription: Subscription; constructor(private followService: SpotifyFollowService, private el: ElementRef) { } @HostListener('click') onclick() { this.subscription = this.followService.followArtists(this.id).subscribe( data => { this.checkFollowingArtist(); } ); } ngOnChanges() { this.checkFollowingArtist(); } checkFollowingArtist() { if (this.id != null) { this.subscription = this.followService.checkFollowingArtist(this.id).subscribe( following => { const follow = following[0]; if (follow === true) { return this.el.nativeElement.value = 'Following'; } else { return this.el.nativeElement.value = 'Follow'; } } ); } } ngOnDestroy() { this.subscription.unsubscribe();
! Comparativa*entre*Angular*y*AngularJS.*Evolución*a*Angular*5.!
Angela!Serrano!Sánchez!! ! Página!97!!
} }
!
En!AngularJS!se!haría!utilizando!el!método!.directive()!de!la!siguiente!manera;!
angular.module('appModule', []) .directive(’appFollowing’, ['SpotifyArtist', function(SpotifyArtist) { function following(scope, element, attr) { element.on('click', function(event){ event.preventDefault(); var promise = SpotifyArtist.followArtist(scope); checkFollowingArtist(); }); function checkFollowingArtist() { var promise = SpotifyArtist.checkFollowingArtist(scope); if (promise === true){ element.text('Following'); } else { element.text('Follow'); } } } return { following: following, scope: { id: ‘=’ }, template: 'artist.html' }; }]);
!
En!la!anterior!directiva!AngularJS!se!indica!sobre!qué!plantilla!y!sobre!qué!variable!
se! va! a! hacer! uso! de! la! directiva.! Es! decir,! en! la! plantilla! artista.html! se! recoge! el!
identificador!del!artista!sobre!el!que!se!hará!la!comprobación!de!si!el!usuario!sigue!o!no!
a!dicho!artista!cada!vez!que!se!lance!el!evento!click!al!pulsar!sobre!el!botón.!!
En!SpotifyAngular!esta!directiva,!determina!si!el!usuario!sigue!o!no!a!ese!artista,!
cambiando!el!texto!del!botón!según!corresponda.!
! [UPM]!Máster*en*Ingeniería*Web!
Página!98!
!Imagen*27.*El*usuario*sigue*al*artista*
3.2.6.! FILTROS VS PIPES
Lo!que!en!Angular!se!conoce!como!pipe,!en!AngularJS!se!denomina!filtro.!En!ambos!
casos!el!uso!es!el!mismo;!transformar!la!salida!de!un!dato!en!la!vista.!!
También! la! sintaxis! es! la!misma,! a! la! derecha! de! la! expresión! a! transformar! se!
escribe!una!barra!vertical,!seguida!del!nombre!del!filtro!o!pipe!a!aplicar.!
Tanto!en!Angular,!como!en!AngularJS!la!sintaxis!es!la!siguiente;!
<td> {{element.duration_ms | date:'mm:ss'}} </td>
!
Muchos! de! los! filtros! que! existen! en! AngularJS,! existen! también! en! Angular! a!
excepción!de! filter!y!orderBy*que!por!motivos!de!rendimiento!se!dejaron! fuera!de! la!
nueva!versión!de!Angular.!
El! resto!de! filtros!que!ya!existían!en!AngularJS! (currency,!date,! json,!uppercase,!
lowercase,! number)! se! mantienen! igual! en! Angular! a! excepción! de! limitTo,! que! en!
Angular!cambia!su!nomenclatura!por!slice.!
Este! filtro! crea!un!nuevo!array!de! strings! conteniendo! solamente! los!elementos!
especificados!por!la!longitud!establecida!por!los!parámetros!limit!y!begin.!
!{{ limitTo_expression | limitTo : limit : begin}}
!
En!Angular!la!funcionalidad!se!mantiene,!pero!pasa!a!llamarse!slice!y!el!orden!de!
los!parámetros!cambia,!para!establecer!primero!la!posición!de!inicio!y!determinar!luego!
el!número!de!posiciones!que!se!van!a!recoger!en!el!nuevo!array.!
!{{ limitTo_expression | limitTo : begin : limit}}
!
Angular!introduce!además!nuevos!filtros!como!decimal,!percent,!titlecase!y!async,!
por!ejemplo.!!
! Comparativa*entre*Angular*y*AngularJS.*Evolución*a*Angular*5.!
Angela!Serrano!Sánchez!! ! Página!99!!
Para!definir!un!filtro!en!AngularJS!se!usa!la!función!.filter()!sobre!el!módulo!donde!
se! quiere! utilizar.! Se! sigue! como! ejemplo! la! pipe! utilizada! en! SpotifyAngular,! que!
reemplaza!el!carácter!de!ampersand*(&)!por!otro!a!elección!del!usuario,!o!si!no!se!pasa!ninguna!máscara,!se!reemplazará!por!el!valor!por!defecto!‘and’.!
import { Pipe, PipeTransform } from '@angular/core'; @Pipe({ name: 'replaceAmp' }) export class ReplaceAmpPipe implements PipeTransform { transform(value: string, args?: string): string { let val = value; if (args) { val = value.replace('&', args); } else { val = value.replace('&', 'and'); } return val; } } !
En!AngularJs!el!filtro!personalizado!quedaría!muy!similiar,!aquí!habría!que!utilizar!
el!método!.filter().!!
angular.module('replaceAmp', []) .filter('replaceamp', function() { return function(input, replaceWith) { var out = ''; if(replaceWith!=null){ out = input.replace('&', replaceWith); } else { out = input.replace('&', 'and'); } return out; }; })
!
En! SpotifyAngular,! este! filtro! se! aplica! a! los! nombres! de! artistas! en! la! vista! del!
detalle! de!una!Playlist.!Un!ejemplo!de! su! aplicación! y! visualización! se!muetra! en! las!
siguientes!imágenes.!
! [UPM]!Máster*en*Ingeniería*Web!
Página!100!
!Imagen*28.*Visualización*del*nombre*del*artista*sin*filtro*
!Imagen*29.*Visualización*del*nombre*del*artista*con*filtro*
3.2.7.! SERVICIOS E INYECCIÓN DE DEPENDENCIAS
Como!en!casi!todos!los!elementos!de!las!arquitecturas!de!AngularJS!y!Angular,!los!
servicios!y! la! inyección!de!dependencias!es!otro!punto!en!el!que!ambos! frameworks!
coinciden!conceptualmente.!
Los!servicios!representan!funcionalidad!transversal!a! la!aplicación,!que!no!sirven!
necesariamente!en!un!único!componente!o!controlador.!La!forma!de!proveer!el!servicio!
a!los!elementos!que!lo!necesiten!es!a!través!de!la!inyección!de!dependencias!tanto!en!
Angular,!como!en!AngularJs.!
Volviendo!a!un!plano!más!práctico!con!SpotifyAngular.!
@Injectable() export class SpotifyPlaylistService { userId: string; baseUrl: string; constructor(public http: HttpClient) { this.userId = localStorage.getItem('user'); this.baseUrl = ('https://api.spotify.com/v1/users/').concat(this.userId).concat('/playlists'); } public getPlaylists(): Observable<Playlists> {
! Comparativa*entre*Angular*y*AngularJS.*Evolución*a*Angular*5.!
Angela!Serrano!Sánchez!! ! Página!101!!
return this.http.get<Playlists>(this.baseUrl); } public getPlaylist(playlistId: string): Observable<Playlist> { return this.http.get<Playlist>(this.baseUrl.concat('/').concat(playlistId)) .pipe(map(resp => <Playlist>resp)); } public getPlaylistTracks(playlistId: string): Observable<Tracks> { return this.http.get<Tracks>(this.baseUrl.concat('/').concat(playlistId).concat('/tracks')) .pipe(map(resp => <Tracks>resp)); } public createPlaylist(playlistName: string, playlistDesc: string,) { return this.http.post(this.baseUrl, {name: playlistName, description: playlistDesc}); } public deleteTrackFromPlaylist(playlistId: string, trackUri: string) { return this.http.request('DELETE', this.baseUrl.concat('/').concat(playlistId).concat('/tracks'), { body: { tracks: [{uri: trackUri}] } }); } public addTrackToPlaylist(trackUri: string, playlistId: string) { return this.http.post(this.baseUrl.concat('/').concat(playlistId).concat('/tracks'), { uris: [trackUri]}); } public search(q: string, type: string): Observable<any> { return this.http.get('https://api.spotify.com/v1/search?q=' + q + '&type=' + type + '&limit=5') .pipe(map(resp => resp)); } }
Aunque! en! la! clase! anterior,! hay! definidas! funciones! que! llaman! al! servidor!
mediante! peticiones! http,! este! punto! se! centra! en! la! organización! y! creación! de!
servicios,!que!proveen!a!otros!elementos!de!cierta!funcionalidad.!!
! [UPM]!Máster*en*Ingeniería*Web!
Página!102!
Las!diferencia!de!cómo!Angular!y!AngularJS!se!conectan!con!el!servidor!será!tratada!
más!adelante.!!
Se!implementa!ahora!con!AngularJS.!
angular.module('appModule') .factory('spotifyPlaylist', function($http) { return{ var userId = localStorage.getItem('user'); var baseUrl = ('https://api.spotify.com/v1/users/').concat(userId).concat('/playlists'); getplaylists : function getPlaylists() { $http.get(baseUrl).then(function(){}, function(){}); }, getplaylist: function(id) { $http.get(baseUrl.concat(id)).then(function(){}, function(){}); }, getPlaylistTracks: function(id) { $http.get(baseUrl.concat(id).concat('/tracks').then(function(){}, function(){}); }, createPlaylist: function(playlistName, playlistDesc) { $http.post(baseUrl, {name: playlistName, description: playlistDesc }).then(function(){}, function(){}); }, deleteTrackFromPlaylist : function(id, trackUri) { $http.delete(baseUrl.concat(id).concat('/tracks'), tracks: [{uri: trackUri}).then(function(){}, function(){}); }, addTrackToPlaylist: function (id) { $http.post(baseUrl.concat(id).concat('/tracks'), { uris: [trackUri]}).then(function(){}, function(){}); }, search: function (q, type) { $http.get('https://api.spotify.com/v1/search?q=' + q + '&type=' + type + '&limit=5').then(function(){}, function(){}); }, } }]);
!
En!AngularJS,!los!servicios!pueden!crearse!con!.service()!o!.factory(),!la!diferencia!
entre!ambos!métodos!es!que!service!es!un!constructor!que!puede!instanciarse!creando!
! Comparativa*entre*Angular*y*AngularJS.*Evolución*a*Angular*5.!
Angela!Serrano!Sánchez!! ! Página!103!!
un!servicio!con!new!y!factory!es!simplemente!una!función!que!devuelve!un!objeto!de!
forma!explícita!creando!la!instancia!cuando!se!llama.!
En!la!aplicación,!este!servicio!se!declara!de!forma!global!añadiendo!la!dependencia!
al! array! providers! del! módulo! principal,! y! luego! se! utiliza! en! el! componente!
playlist.component.ts! inyectando!el! servicio!en!el! constructor!de! la! clase!para!poder!
acceder!a!las!funciones!del!servicio!y!hacer!llamadas!al!servidor.!
@Component({ selector: 'app-playlists', templateUrl: './playlists.component.html', styleUrls: ['./playlists.component.css'] }) export class PlaylistsComponent implements OnInit, OnDestroy { playlists: Playlists; playlistName: string; playlistDesc: string; private subscription: ISubscription; // Se inyecta el servicio en el componente constructor(private playlistService: SpotifyPlaylistService, public dialog: MatDialog ) { } ngOnInit() { this.getPlaylists(); } ngOnDestroy() { this.subscription.unsubscribe(); } getPlaylists(): Playlists { this.subscription = this.playlistService.getPlaylists().subscribe( playlists => { this.playlists = playlists; } ); return this.playlists; } // Resto de métodos del componente {...} }
!
! [UPM]!Máster*en*Ingeniería*Web!
Página!104!
Para!inyectar!el!servicio!en!su!componente!correspondiente,!se!añadiría!al!array!de!
dependencias!de!.component(),!ya!que!como!se!vio!en!el!apartado!de!la!comparativa!de!
componentes,! se! opta! por! esta! técnica! (arquitectura! basada! en! componentes)! para!
transformar!SpotifyAngular!a!AngularJS.!
angular. module('appModule'). component('playlists', { templateUrl: 'playlists.component.html', controller: ['spotifyPlaylist', function PlaylistController($scope,spotifyPlaylist) { var self = this; self.$onInit = function () { self.playlists = spotifyPlaylists.getPlaylists(); }; // Resto de métodos del controlador {...} } ] });
!
En!SpotifyAngular,!la!llamada!a!la!función!getPlaylists()!del!servicio!inyectado,!envía!
una! petición! al! servidor! para! recuperar! la! información! de! las! playlists! públicas! del!usuario.!En!este!caso!esa!información!se!muestra!en!el!combo!de!“Playlists”!de!la!barra!
de!navegación.!
!Imagen*30.*Playlists*recuperadas*de*la*petición*al*servidor*
3.2.8.! OBSERVABLES VS PROMESAS
Aunque! Angular! puede! utilizar! promesas! para! recuperar! datos! en! tareas!
asíncronas,!gracias!a!la!librería!RxJS,!suele!utilizar!observables!porque!presentan!algunas!
ventajas! sobre! las! promesas! como! que! los! observables! no! se! lanzan! hasta! que! son!
suscritos,!en!cambio!las!promesas!se!ejecutan!inmediatamente!tras!su!creación.!!
! Comparativa*entre*Angular*y*AngularJS.*Evolución*a*Angular*5.!
Angela!Serrano!Sánchez!! ! Página!105!!
El! método! .subscribe()! ejecuta! el! comportamiento! definido! una! vez! y! tiene! un!
cálculo!propio,!pero!pueden!volver!a!llamarse!recalculando!los!valores!cada!vez.�
Las!promesas!se!ejecutan!de!forma!inmediata,!y!solo!una!vez,!por!lo!que!el!cálculo!
del!resultado!se!inicia!cuando!se!crea!la!promesa!y!no!hay!forma!de!reiniciar!el!trabajo.!!
Además! los! observables! pueden! proporcionar! muchos! valores,! las! promesas!
proporcionan!uno.! Esto! hace!que! los! observables! sean!útiles! para! obtener!múltiples!
valores!a!lo!largo!del!tiempo!de!vida!de!la!aplicación.�
Otra! ventaja! es! que! los! observables! diferencian! entre! encadenamiento! y!
suscripción.!Las!promesas!solo!tienen!cláusulas!.then!().!Esto!hace!que!los!observables!
sean!útiles!para!ejecutar!transformaciones!complejas!y!ser!utilizadas!por!otra!parte!de!
la!aplicación!sin!ejecutar!la!tarea!hasta!que!sea!suscrita.�
En! los! observables! .subscribe()! sirve! además! para! manejar! los! errores! que! se!
generen.!Las!promesas,!en!cambio!propagan!los!errores!a!las!promesas!hijas.!Esto!hace!
que!los!observables!sean!útiles!para!un!manejo!de!errores!centralizado!y!predecible.!
Por! último,! otra! ventaja! importante! es! que! las! suscripciones!pueden! cancelarse!
gracias!al!método!.unsubscribe(),!las!promesas!una!vez!lanzada!la!creación!no!se!pueden!
cancelar!(Google,!Angular,!2018).!
3.2.9.! FORMULARIOS
En!esta!caso,!la!comparativa!se!enfoca!en!los!formularios!basados!en!plantilla,!ya!
que!en!AngularJS!no!existen!los!formularios!reactivos.!!
Los!formularios!basados!en!plantillas!de!Angular!y!los!formularios!de!AngularJS,!son!
bastante! similares.! Ambos! utilizan! la! directiva! ngModel! y! ngomodel! respectivamente!
para!tomar!el!control!de!los!elementos!del!formulario.!
La!aplicación!de!SpotifyAngular!solamente!incluye!dos!pequeños!formularios;!el!de!
la!búsqueda,!ubicado!en!la!barra!de!navegación!y!el!de!creación!de!playlisist,!al!que!se!accede!desde!el!combo!de!playlists!también!en!la!barra!de!navegación.!
No!se!puede!realizar!la!comparativa!con!el!primero!de!ellos,!porque!aunques!sólo!
esté!compuesto!por!dos!controles,!se!ha!utilizado!la!técnica!de!formulario!reactivo!para!
implementarlo.!
Se! realiza! la! comparativa! sobre! el! formulario! de! creación! de! playlist.! En!SpotifyAngular!para!crear!este!formulario!se!ha!hecho!uso!de!Angular!Material,!por!lo!
que!el!funcionamiento!del!formulario!puede!diferir!un!poco!de!cómo!sería!un!formulario!
basado! en! plantilla! normal,! aunque! en! el! conversión! a! Angular! se! asumirá! que! el!
formulario!funciona!sin!Angular!Material.!
De!esta!forma,!el!código!HTML!del!formulario!en!la!aplicación!es;!
<h2 mat-dialog-title>Create Playlist</h2> <div mat-dialog-content> <p>New Playlist</p> <mat-form-field> <input matInput [(ngModel)]="data.playlistName" placeholder="Name" required>
! [UPM]!Máster*en*Ingeniería*Web!
Página!106!
</mat-form-field> <mat-form-field> <input matInput [(ngModel)]="data.playlistDesc" placeholder="Description"> </mat-form-field> </div> <div mat-dialog-actions> <button mat-button (click)="onNoClick()">Cancel</button> <button mat-button [mat-dialog-close]="data" cdkFocusInitial>Ok</button> </div>
!
Si!esto!fuese!un!formulario!normal!de!Angular!quedaría!como;!
<form (ngSubmit)="onSubmit()" #appform></form> <input [(ngModel)]="data.playlistName" type="text" placeholder="Name" required name="playlistName"> <input [(ngModel)]="data.playlistDesc" type="text" placeholder="Description" name="playlistDesc"> <button [disabled]="!appform.form.valid">OK</button> </form>
!
Que!se!transforma!ahora!en!un!formulario!AngularJS!
<form> <label>Name: <input type="text" ng-model="data.playlistName" required/></label> <label>Description: <input type="text" ng-model="data.playlistDesc" /></label> <input type="submit" ng-click="submit(data)" value="Save" /> </form>
!
Se!aprecia!que!la!directiva!fundamental!es!ng!model!en!ambos!casos,!la!diferencia!
está!en!la!función!que!manipulará!los!datos!del!formulario!una!vez!que!el!usuario!quiera!
guardarlos.!!
En!Angular,!la!función!va!asociada!al!evento!ngSubmit!y!no!se!ejecutará!hasta!que!
el!botón!de!tipo!submit!asociado!sea!pulsado,!que!por!otra!parte!no!estará!activo!hasta!que! se! cumplan! las! validaciones,! concretamente! la! validación! required! del! campo!
playlistName.!!En! AngularJS! en! cambio! la! función! está! asociada! directamente! al! input! de! tipo!
submit!y!escucha!el!evento!click,!no!una!directiva!cómo!en!el!caso!de!Angular.!
En!este!caso,!no!se!han!insertado!validaciones!en!los!formularios!más!allá!de!las!
que!vienen!por!defecto!con!HTML,!pero!si!se!quisiera!crear!una!validación!en!AngularJS,!
igual!que!en!Angular,!se!haría!creando!una!directiva,!con!la!particularidad!de!que!habría!
que! añadirle! la! propiedad! {require:! ngModel},! para! identificar! que! se! trata! de! una!
validación.!
! Comparativa*entre*Angular*y*AngularJS.*Evolución*a*Angular*5.!
Angela!Serrano!Sánchez!! ! Página!107!!
3.2.10.! NAVEGACIÓN Y ROUTING
El!módulo!que!proporciona! la!navegación!y!el! enrutamiento!en!AngularJS,! es!el!
módulo!externo!ngRoute!y!debe!descargarse!y!añadirse!manualmente!a!la!aplicación!del!
mismo!modo!que!el!framework!en!sí.!!Aunque,!si!se!utiliza!el!esqueleto!de!aplicación!AngularJS!del!proyecto!angularoseed,!
en!el!fichero!de!configuración!bower.json!ya!viene!integrada!la!dependencia,!de!forma!
que!si!se!lanza!el!comando!npm*install!dicha!dependencia!se!cargará!automáticamente!
en!la!aplicación.!
Este!módulo!sería!el!equivalente!a!la!librería!@angular/router!de!Angular.!
Se! configura! el!módulo! de! routing! de! SpotifyAngular! en! AngularJS! para! ver! las!
diferencias.!
En!Angular!es!necesario!importar!la!clase!Routes!y!el!módulo!RouterModule!para!
crear!la!configuración!de!rutas!que!controlarán!la!navegación!de!la!aplicación.!Después,!
el!módulo!routingModule!creado!se!importa!en!el!módulo!principal.!!!
!
import { Routes, RouterModule } from '@angular/router'; const ROUTES: Routes = [ { path: '', redirectTo: 'login', pathMatch: 'full' }, { path: 'login', component: SignInComponent }, { path: 'callback', component: CallbackComponent }, { path: 'main', component: HeaderComponent }, { path: 'playlist/:id', component: PlaylistDetailsComponent}, { path: 'artists/:id', component: ArtistsComponent}, { path: 'albums/:id', component: AlbumsComponent }, { path: 'results', component: SearchResultsComponent }, { path: '**', component: SignInComponent } ]; export const routingModule = RouterModule.forRoot(ROUTES, { useHash: true});
!
En!AngularJS!es!necesario!cargar!el!proveedor!$routerProvider!en!la!configuración!
del! módulo,! y! será! este! proveedor! quien,! mediante! condiciones! .when! defina! la!
configuración!de!rutas!de!la!aplicación.!De!esta!forma,!cada!vez!que!se!navegue!y!!la!ruta!
activada! coincida! con! alguna! condición! de! la! configuración!mostrará! el! componente!
asociado.!
angular. module('appModule'). config(['$locationProvider' ,'$routeProvider', function config($locationProvider, $routeProvider) { $locationProvider.html5Mode(true); $routeProvider. when('/login', {
! [UPM]!Máster*en*Ingeniería*Web!
Página!108!
template: '<sign-in></sign-in>' }). when('/callback', { template: '<callback></callback>' }). when('/main', { template: '<header></header>' }). when('/playlist/:id', { template: '<playlist-details></playlist-details>' }). when('/artists/:id', { template: '<artists></artists>' }). when('/albums/:id', { template: '<albums><albums>' }). when('/results', { template: '<search-results></search-results>' }). otherwise('/login'); } ]);
!
En!este!caso!la!propiedad!template!tiene!asociada!la!plantilla!del!componente!en!
cuestión.!
Para! las! rutas! con! parámetros,! por! ejemplo! albums/:id,! cuando! se! llama! al!
componente!debe!recogerse!el!valor!del!parámetro!:id!de!la!ruta.!Esto!en!Angular!se!
hace!inyectando!en!el!constructor!del!componente!la!clase!ActivatedRoute!del!siguiente!
modo;!
@Component({ selector: 'app-albums', templateUrl: './albums.component.html', styleUrls: ['./albums.component.css'], providers: [ SpotifyAlbumsService ] }) export class AlbumsComponent implements OnInit { album$: Observable<Album>; constructor(private activatedRoute: ActivatedRoute, private spotifyAlbums: SpotifyAlbumsService) { } ngOnInit() { this.album$ = this.activatedRoute.paramMap.pipe( switchMap((params: ParamMap) => this.spotifyAlbums.getAlbumById(params.get('id'))) );
! Comparativa*entre*Angular*y*AngularJS.*Evolución*a*Angular*5.!
Angela!Serrano!Sánchez!! ! Página!109!!
} } !
En! AngularJS! se! inyecta! el! proveedor! $routeParams! al! controlador! para! poder!
recoger!ese!parámetro;!
angular. module('appModule'). component('albums', { templateUrl: 'albums.html', controller: ['$routeParams','SpotifyAlbums', function AlbumsController(($scope, $routeParams, SpotifyAlbums) { var self = this; self.$onInit = function () { self.album = SpotifyAlbums.getAlbumById({id: $routeParams.id}); }; } ] });
!
Faltaría!entonces!ver!en!qué!parte!de!la!plantilla!se!mostrará!el!componente.!En!
Angular!esto!se!hace!mediante!la!directiva!<routerooutlet></routerooutlet>.!En!el!lugar!
de!la!plantilla!donde!se!coloque!esta!directiva,!será!donde!se!muestren!los!elementos!
asociados!a!la!ruta.!!
El! módulo! ngRoute! en! este! caso! proporciona! la! directiva! ngoview.! La! directiva!
<routerooutlet></routerooutlet>!funciona!como!un!elemento!del!DOM!en!sí!mismo,!no!
es!el!caso!de!ngoview,!por!ese!motivo!debe!ir!asociada!a!un!elemento!HTML,!como!un!
div.!
<body> <div> <div ng-view></div> </div> </body>
!
En!este!ejemplo!se!utiliza!el!componente!de!albums.component.ts!para!realizar!la!
comparativa! con! AngularJS,! aunque! en! la! aplicación! de! SpotifyAngular! las! rutas! con!
parámetros!también!se!utilizan!para!navegar!al!detalle!de!una!playlist!o!a!los!datos!de!un!artista!concreto.!En!todos!los!casos!la!ruta!contiene!el!identificador!de!dichos!datos!
especificado!por!la!API!de!Spotify.!Si!por!ejemplo,!se!navega!a!un!artista,!la!ruta!de!la!
navegación!apuntará!a!un!id!específico,!tal!y!como!muestra!la!imagen!siguiente.!
! [UPM]!Máster*en*Ingeniería*Web!
Página!110!
!Imagen*31.*Ruta*de*navegación*con*el*identificador*del*artista*
En! SpotifyAngular! existe! además! otro! módulo! de! enrutamiento,! con! rutas!
específicas!del!perfil!del!usuario!/user!y!/user/following!que!no!se!cargan!en!el!módulo!
de!enrutamiento!principal.!En!este!módulo!se!realiza!una!configuración!de!ruta!hija.!
const userRoutes: Routes = [ { path: 'user', component: UserComponent, children: [ { path: 'following', component: FollowingComponent } ] } ]; @NgModule({ imports: [ RouterModule.forChild(userRoutes) ], exports: [ RouterModule ] }) export class UserRoutingModule { }
!
Este!concepto!no!existe!en!AngularJS.! La! forma!de!especificar! rutas!hija! sería! la!
siguiente;!
angular. module('userModule'). config(['$locationProvider' ,'$routeProvider', function config($locationProvider, $routeProvider) { $locationProvider.html5Mode(true);
! Comparativa*entre*Angular*y*AngularJS.*Evolución*a*Angular*5.!
Angela!Serrano!Sánchez!! ! Página!111!!
$routeProvider. when('/user', { template: '<user></user>' }). when('/user/following', { template: '<following></following>' }) } ]);
Es! decir,! la! forma! de! especificar! rutas! hija,! sería! componer! la! ruta! completa!
‘/user/following’y!apuntar!al!componente!que!se!quiere!visualizar.!
3.2.11.! CONEXIÓN CON EL SERVIDOR
Para!las!conexiones!con!el!servidor!AngularJS!utiliza!el!servicio!$http.!Este!servicio!
es!una!función!que!toma!un!único!argumento,!un!objeto!de!configuración,!que!se!utiliza!
para! generar! una! solicitud! HTTP! y! devuelve! una! promesa! que! se! resuelve! (solicitud!
exitosa)!o!se!rechaza!(solicitud!erronea)!con!un!objeto!de!respuesta.!Debe!inyectarse!en!
el!controlador!o!servicio!que!necesite!establecer!conexiones!con!el!servidor.!
En!Angular!HttpClient!es!quien!se!encarga!de!realizar!estas!tareas,!con!la!diferencia!
de!que,!en!vez!de!promesas!la!gran!mayoría!de!las!veces!se!devuleven!observables.!Suele!
inyectarse! en! otros! servicios! implementados! en! la! aplicación! para! que! la! lógica! de!
conexión!al!servidor!no!se!implemente!directamente!en!en!el!componente.!
En!Angular! las!peticiones!pueden!configurarse!de!dos!maneras!distinas,!con!una!
función! o! con! el! método! simplificado.! Reutilizando! los! servicios! anteriormente!
mencionados!en!el!apartado!de!la!comparativa!de!servicios,!la!petición;!
public getPlaylists(): Observable<Playlists> { return this.http.get('https://api.spotify.com/v1/me/playlists').pipe(map(resp => <Playlists>resp));
} !
Podría!representarse!en!AngularJS!como;!
a)! Por!función! $http({ method: 'GET', url: 'https://api.spotify.com/v1/me/playlists', });
!
b)! Por!función!simplificada! $http.get('https://api.spotify.com/v1/me/playlists') !
!
! [UPM]!Máster*en*Ingeniería*Web!
Página!112!
Para!las!peticiónes!que!tienen!que!enviar!datos!como!POST,!PUT!o!DELETE!debe!
añadirse!el!parámetro!‘data’!con!la!información!correspondiente.!Por!ejemplo;!
public createPlaylist(playlistName: string, userId: string) {
return this.http.post('https://api.spotify.com/v1/users/' + userId + '/playlists', {name: playlistName}); }
!
En!AngularJS! la!petición!de!POST,!siguiendo! las!dos!técnicas!anteriores!quedaría!
como;!
a)! Por!función! $http({ method: 'POST', url: 'https://api.spotify.com/v1/users/' + userId + '/playlists', data: {name: playlistName} });
!
b)! Por!función!simplificada!
$http.post('https://api.spotify.com/v1/users/' + userId + '/playlists', data: {name: playlistName}); !
La!forma!establecer!una!cabecera!en!las!peticiónes!con!AngularJS!es!creando!un!objeto!
de!configuración!y!luego!se!pasa!como!parámtero!en!la!petición;!
$http({ method: 'POST', url: 'https://api.spotify.com/v1/users/' + userId + '/playlists', headers: { Authorization: 'Bearer ' + token }, data: {name: playlistName} }); !
Aunque!también!puede!definirse!a!través!del!proveedor!$httpProvider;!
$httpProvider.defaults.headers.get = {Authorization: 'Bearer ' + token}
!
! !
! Comparativa*entre*Angular*y*AngularJS.*Evolución*a*Angular*5.!
Angela!Serrano!Sánchez!! ! Página!113!!
4.! CONCLUSIONES. VENTAJAS Y FUTURO DE ANGULA
Una!vez!estudiada!la!arquitectura!de!Angular!y!hecha!la!comparativa!práctica!con!
AngularJS,! llega!el!momento!de!explicar!cuáles!son!las!ventajas!que!presenta!Angular!
sobre!AngularJS.!
Como!ya!se!ha!comentado!en!diferentes!puntos!de!este!documento,!Angular!se!
reescribió!con!la!idea!de!mejorar!AngularJS.!Entre!las!muchas!ventajas!que!presenta!el!
nuevo! framwork,! se! destacan! principalmente! las! que! se!muestran! en! los! siguientes!
apartados.!
4.1.! VENTAJAS
4.1.1.! PUESTA EN MARCHA
Una!de! las!ventajas!más!destacables,!es! la!puesta!en!marcha!de!un!proyecto!en!
Angular.!La!utilización!de!Angular!CLI!automatiza!gran!parte!de!las!tareas!de!generación,!
instalación!e!implementación!de!una!aplicación!Angular,!mientras!que!en!AngularJS!la!
mayoría! de! procesos! de! creación! de! elementos! e! instalación! de! dependencias! sigue!
siendo!manual.!Esta!herramienta!reduce!el!tiempo!de!inicio!y!puesta!en!marcha!de!un!
proyecto.!
4.1.2.! MODULARIDAD
Por!otro!lado!que!la!arquitectura!de!Angular!se!base!en!componentes!y!módulos!
mejoran!la!modularidad!de!la!aplicación!y!por!tanto!su!reutilización!en!otras!partes!de!
la! aplicación! e! incluso! en! otras! aplicaciones.! En! AngularJS! los! módulos! son!
principalmente! contenedores! que! agrupan! una! cierta! funcionalidad! mediante!
inyectores!de!dependencias,!y!no!se!cargan!de!forma!asíncrona!la!primera!vez!que!una!
dependencia!es!solicitada.!
La!carga!diferida!de!módulos!debería!ser!algo!nativo!del!framework!y!transparente!
al!desarrollador,!como!ocurre!en!Angular.!
4.1.3.! ARQUITECTURA BASADE EN COMPONENTES
Otra!de! las! principales! ventajas! en! cuanto! a! la! arquitectura! de!Angular,! son! los!
componentes!frente!a!los!controladores!y!la!variable!$scope!de!AngularJS.!El!scope!en!
AngularJS!es!un!objeto!que!hace!referencia!al!modelo!de!la!aplicación,!es!el!contexto!de!
ejecución! para! las! expresiones.! La! variable! $scope! se! utiliza! para! comunicar! un!
! [UPM]!Máster*en*Ingeniería*Web!
Página!114!
controlador!con!una!plantilla,!aunque!en!las!últimas!versiones!de!AngularJS!se!introdujo!
el!concepto!de!controllerAs!para!sustituir!el!uso!explícito!de!$scope.!Esta!práctica!es!
recomendada! por! numerosos! autores,! principalmente! por! John! Papa! ya! que!
controllerAs! sirve! para! determinar! a! qué! contexto! de! la! aplicación! corresponde! un!
determinado!método!o!propiedad.!Esto!es!útil!cuando!en!la!misma!plantilla!se!utilizan!
ámbitos!anidados!y!simplifica!la!lectura!del!código!y!el!mantenimiento!de!la!aplicación.!
Aún!así,!para!evitar!confusiones!y!malas!prácticas,!en!Angular!desaparecen!estos!
elementos!para!dejar!paso!a!la!anotación!@Component!y!sus!metadatos,!que!son!los!
encargados!de!vincular!la!lógica!de!la!clase!de!un!componente!con!una!plantilla!concreta!
en! el! mismo! contexto.! Siempre! que! se! manipulan! datos! en! una! plantilla! está!
perfectamente! establecida! su! relación! con! un! componente,! esto! simplifica!
significativamente!la!tarea!de!desarrollar!código!legible!y!mantenible!en!una!aplicación.!
4.1.4.! INYECCIÓN DE DEPENDENCIAS
La! inyección!de!dependencias!también!se!ha!mejorado!en!Angular.!En!AngularJS!
hay! múltiples! mecanismos! de! inyección! de! dependencias.! Por! ejemplo! se! pueden!
inyectar!dependencias!en!múltiples!lugares!de!diferentes!maneras:!en!una!función!de!
enlace! por! posición,! en! la! definición! de! la! directiva! por! nombre,! en! la! función! del!
controlador!por!nombre,!etc.!!
En!Angular!las!dependencias!se!inyectan!a!través!del!controlador!de!la!clase!que!
requiera! utilizar! esa! dependencia.! El! hecho! de! que! haya! una! sola! forma!de! inyectar!
dependencias! facilita! el! aprendizaje! del! framework.! Además,! al! existir! un! árbol! de!
inyección! de! dependencias! jerárquico,! si! un! componente! no! tiene! una! dependencia!
definida,! la! búsqueda! se! delega! a! los! nodos! superiores! del! árbol.! De! esta! forma! se!
garantiza!que!la!dependencia!casi!siempre!va!a!ser!resuelta.!
4.1.5.! RENDIMIENTO
Las!mejoras!de!los!puntos!anteriores!se!ven!reflejadas!en!términos!de!rendimiento!
en!una!aplicación!Angular.!!
Otro!factor!importante!en!el!aumento!del!rendimiento!en!aplicaciones!Angular!es!
el! sistema! de! detección! de! cambios! que! éste! implementa.! Aunque! este! sistema! de!
Angular!pueda!suponer!perdidas!de!rendimiento!a!la!hora!de!ejecutar!una!aplicación,!
existen!mecanismos!para!evitar!que!se!escaneen!partes!del!árbol!de!componentes!como!
hacer!que!los!modelos!sean!observables,!de!esta!forma!!si!existen!o!no!cambios!Angular!
será! informado! por! el! mecanismo! de! observables! y! no! será! necesario! activar! la!
detección!de!cambios.!Del!mismo!modo!se!puede!hacer!que!el!modelo!sea!inmutable,!
utilizando!por!ejemplo!el!fichero!immutable.js11.!
Con!todo!esto!Angular!mejora!hasta!en!cinco!veces!el!rendimiento!sobre!AngularJS.!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!11!Librería!JavaSrcript!desarrollada!por!Facebook!para!usar!colecciónes!de!datos!inmutables.!
! Comparativa*entre*Angular*y*AngularJS.*Evolución*a*Angular*5.!
Angela!Serrano!Sánchez!! ! Página!115!!
4.1.6.! ORIENTADO A MÓVILES
Cuando!AngulasJS!se!implementó!no!se!contempló!su!utilización!en!el!desarrollo!
de!aplicaciones!móviles.!Este!es!otro!de!los!puntos!a!favor!de!Angular,!que!el!framework!
puediese!aplicarse!en!el!desarrollo!de!distintos!dispositivos!fue!un!factor!clave.!!
Angular!junto!con!NativeScript12,!permiten!desarrollar!aplicaciones!móviles!nativas!
para!iOS!y!Android!
!Imagen*32.*Angular*en*el*desarrollo*de*aplicaciones*móviles*
4.1.7.! LIBRERÍAS DE TERCEROS
La! modularidad! de! Angular! y! la! herramienta! de! instalación! de! dependencias!
Angular!CLI,!hacen!que!sea!mucho!más!fácil!instalar!librerías!externas!que!proporcionan!
funcionalidad!extra!a!las!aplicaciones.!
Entre!estas!librerías!hay!que!hacer!especial!mención!a!Angular!Materials,!utilizada!
en!algunas!partes!de!la!aplicación!desarrollada,!que!proporciona!una!serie!de!directivas!
que!sirven!para!diseñar! la!apariencia!de! la!aplicación!en!base!a! la!guía!de!diseño!de!
elementos!de!Google,!Material!Design.!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!12!Framework!de!código!abierto!para!desarrollar!aplicaciones!nativas!iOS!y!Android.!
! [UPM]!Máster*en*Ingeniería*Web!
Página!116!
!Imagen*33.*Formulario*en*PopUp*creado*con*el*elemento*'Dialog'*de*Angular*Materials*
!En! AngularJS! la! alternativa! es! AngularUI,! aunque!más! que! una! librería,! es! una!
colección!de!módulos.!Cada!uno!de!estos!módulos!!se!instala!en!la!aplicación!de!forma!
independiente,! como! por! ejemplo! UI! Bootstrap! o! el! módulo! de! navegación! y!
enrutamiento!UI!Router.!
4.1.8.! TYPESCRIPT VS JAVASCRIPT
Por! último,! destacar! el! lenguaje! de! programación! utilizado! en! cada! framework.!
Mientras!que!AngularJS!utiliza!el!lenguaje!de!JavaScript,!en!Angular!las!aplicaciones!se!
desarrollan!utilizando!principalmente!TypeScript.!
TypeScript! en! un! superconjunto! de! JavaScript,! que! facilita! la! aplicación! del!
paradigma!de!la!programación!orientada!a!objetos!en!el!desarrollo!de!aplicaciones,!así!
como!el!tipado!estático!de!propiedades!y!atributos.!
El! tipado! supone! una! reducción! considerable! de! errores! humanos! en! la!
programación!ya!que!se!evita!que!una!variable!sea!sobrescrita!o!que!la!aplicación!arroje!
errores!si!se!le!asigna!un!valor!con!un!tipo!distinto!al!que!debería!utilizar.!
Del!mismo!modo!la!orientación!a!objetos!permite!crear!una!estructura!más!clara!
de!elementos!y!facilita!la!organización!de!la!aplicación!en!clases,!que!además!podrán!
extender!otras! clases!o! implementar! interfaces,! gracias!a! los! conceptos!de!herencia,!
encapsulamiento!y!polimorfismo!inherentes!a!este!paradigma.!
4.1.9.! CURVA DE APRENDIZAJE
En!cuanto!a! la!curva!de!aprendizaje!de!Angular,!dependerá!del!desarrollador!en!
cuestión.!
Al!ser!un!lenguaje!orientado!a!objetos,!TypeScript!puede!resultar!bastante!parecido!
a!otros!lenguajes!que!se!basan!en!este!paradigma!como!Java!o!C#.!
! Comparativa*entre*Angular*y*AngularJS.*Evolución*a*Angular*5.!
Angela!Serrano!Sánchez!! ! Página!117!!
Si!quien!debe!aprender!Angular!es!un!programador,!cuya!experiencia!previa!se!basa!
en!AngularJS!o!en!JavaScript!puro,!puede!que!introducirse!en!la!estructura!de!Angular!
le! cueste! más! que! a! un! desarrollador! acostumbrado! a! trabajar! con! otros! lenguajes!
orientados!a!objetos.!
Esto! puede! suponer! una! ventaja! o! un! inconveniente! dependiendo! del! público!
objetivo!a!quien!se!pregunte.!
4.2.! FUTURO DE ANGULAR
La! reimplementación! de! Angular! cambió! radicalmente! la! concepción! de! la!
arquitectura!y!el! funcionamiento!de!AngularJS,!aportando!una!nueva!visión!sobre! los!
frameworks*frontFend,!mejorando!la!productividad,!el!rendimiento!de!las!aplicaciones!y!
los!tiempos!de!desarrollo.!
De!hecho!la!tendencia!ha!ido!al!revés,!no!es!sólo!el!hecho!de!que!Angular!sea!un!
framework!totalmente!nuevo!e!idependiente!de!AngularJS,!sino!que,!todas!las!mejoras!
introducidas!en!Angular!han! intendado! implementarse!en!AngularJS.!A!este! respecto!
cabe! destacar! la! aparicion! del! elemento! component! en! AngularJS! 1.5! para! intentar!
aplicar!el!mismo!patrón!de!desarrollo!que!en!Angular!basado!en!componentes.!
Aunque!ahora,!con!la!entrada!en!matenimiento!a!largo!plazo!este!mismo!año!de!
AngularJS!en!su!versión!1.7,!puede!decirse!que!este!framework!ha!entrado!sus!últimos!
años!de!vida!útil.!Esto!supondrá!a!las!aplicaciones!que!hay!en!el!mercado!desarrolladas!
bajo!esta!tecnología,!bien!migrar!a!Angular,!o!bien!optar!por!rehacer!la!aplicación!con!
otras!tecnologías!disponibles.!
Es!cierto!que!el!futuro!de!una!tecnología!siempre!es!desconcertante,!pues!nunca!
se!sabe!si!va!a!madurar!y!mantenerse!a!lo!largo!de!los!años!como!Java,!o!por!el!contrario!
va!a!desaparecer!desbancada!por!las!tendencias!del!momento.!El!futuro!de!Angular,!al!
menos!a!corto!plazo,!parece!estable.!Ahora!mismo!es!uno!de!los!frameworks*frontFend!de!referencia!y!el!hecho!de!que!el!equipo!que!está!detrás!de!este!proyecto!sea!Google!
y!que!además!saque!versiones!con!mejoras!y!parches!cada!seis!meses,!lo!convierten!en!
un!tecnología!bastente!valorada!en!el!mundo!laboral.!
A!priori!podría!decirse!que,!por!todo!lo!anterior!y!por!todas!las!ventajas!que!a!dia!
de!hoy!presenta!este!framework,!Angular!se!ha!hecho!con!un!hueco!importante!en!el!
mundo!de!las!tecnologías!frontFend!y!se!le!augura!un!futuro!largo!y!prometedor.!
! Comparativa*entre*Angular*y*AngularJS.*Evolución*a*Angular*5.!
Angela!Serrano!Sánchez!! ! Página!119!!
BIBLIOGRAFÍA
Branas,!R.!(2014).!AngularJS*Essentials.!Birmingham:!Packt!Publishing.!
Clow,!M.!(2018).!Angular*5*Projects.!Sandy!Springs,!Georgia,!Estados!Unidos:!Apress!Media.!
Comparison,!A.!v.oA.oD.!(9!de!Junio!de!2017).!Angular*University.!Recuperado!el!1!de!Julio!de!2018,!de!Angular!University:!https://blog.angularouniversity.io/angularjsovso
angularoanoinodepthocomparison/!
Darwin,! P.! B.! (26! de! Enero! de! 2018).! Stable* AngularJS* and* Long* Term* Support.!Recuperado!el!2018!de!Junio!de!2018,!de!Blog!Angular:!https://blog.angular.io/stableo
angularjsoandolongotermosupporto7e077635ee9c!
Eguiluz,! J.! (2018).! Introducción.! Breve! Historia.! En! J.! Eguiluz,! Introducción* a*JavaScript!(pág.!2).!oo:!LibrosWeb.!
Eguiluz,!J.!(2018).!Introducción.!Breve!Historia.!En!J.!Eguiluz,!Introducción*a*CSS.!oo:!LibrosWeb.!
Google.! (25! de! Julio! de! 2018).!Angular.! Recuperado! el! 1! de!Mayo! de! 2018,! de!
Angular:!https://angular.io/!
Google.! (29!de!Julio!de!2018).!AngularJS.!Recuperado!el!1!de!Mayo!de!2018,!de!
AngularJS:!https://angularjs.org/!
Hernandez,!U.!(1!de!Junio!de!2018).!MVC.!Recuperado!el!1!de!Junio!de!2018,!de!Codigo! Facilito:! https://codigofacilito.com/articulos/mvcomodeloviewocontrollero
explicado!!
Hussain,!A.!(2016).!Angular.*From*theory*to*practice.!oo:!Daolrevo!Ltd!trading.!Microsoft.!(10!de!October!de!2009).!Docs*microsoft.!Recuperado!el!20!de!Mayo!de!
2018,! de! Microsoft! Application! Architecture! Guide:! https://docs.microsoft.com/eno
us/previousoversions/msponop/ee658117(v=pandp.10)#ComponentBasedStyle!
Minar,!I.!(19!de!Julio!de!2012).!AngularJS.!Recuperado!el!30!de!Mayo!de!2018,!de!
Google!+:!https://plus.google.com/+AngularJS/posts/aZNVhj355G2!
Nate!Murray,!F.!C.!(2018).!ngFbook.*The*complete*book*on*Angular*5.!San!Francisco,!California,!Estados!Unidos:!Fullstack.io.!
Solís,!C.!(6!de!Abril!de!2017).!LinkedIn*blog.!Recuperado!el!3!de!Junio!de!2018,!de!La!saga!de!Angular:!https://es.linkedin.com/pulse/laosagaodeoangularoepisodiosojso2o3o
4oyo5ocarlososolis!!
Terreros,! J.!C.! (oo!de! oo!de! oo).!Microsoft.!Recuperado!el!25!de!Mayo!de!2018,!de!
Documentación.! Artículos! Técnicos:! https://msdn.microsoft.com/eso
es/library/bb972268.aspx#EEAA!
!