Escuela*Técnica*Superior*de*Ingeniería*de*Sistemas...

120
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

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.!

! *

! [UPM]!Máster*en*Ingeniería*Web!

! *

! 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!

!

! [UPM]!Máster*en*Ingeniería*Web!!

! 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!

! [UPM]!Máster*en*Ingeniería*Web!

! *

! 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!

!

! [UPM]!Máster*en*Ingeniería*Web!

!

! 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!

!

! [UPM]!Máster*en*Ingeniería*Web!!

! 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.!

!

! [UPM]!Máster*en*Ingeniería*Web!

Página!16!

!

! 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.!

! [UPM]!Máster*en*Ingeniería*Web!

Página!118!

! 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!

!

! [UPM]!Máster*en*Ingeniería*Web!

Página!120!