Manual Angular 2
User Manual:
Open the PDF directly: View PDF .
Page Count: 113 [warning: Documents this large are best viewed by clicking the View PDF Link!]
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 1 de 113
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 2 de 113
Introducción:ManualdeAngular
ComenzamoslaredacciónanuestroManualdeAngular,laevolucióndelframeworkJavascriptmáspopular
paraeldesarrollodeaplicacionesdelladodelcliente.
EnestapáginairásviendolosartículosdelManualdeAngularsegúnlosvayamospublicandoalolargode
lospróximosmeses.
Nuestroobjetivoesrecorrerlaspiezasprincipalesdeestepotenteframeworkyestudiarlosmecanismos
paraeldesarrollodeaplicacioneswebuniversalesconAngular2.Demomentoencontrarásunaestupenda
introducciónaldesarrolloconelnuevoAngular,yabordaremosmuchosmásdetallesenbreve.
EstemanualabordaelframeworkAngular,ensusversiones2enadelante.Cabeaclararque,pocodespués
desalirlaversióndeAngular2,elframeworkcambiódenombreaAngular.Apartirdeaquísehanido
publicandodiversasentregasconnúmerosbasadosenelversionadosemántico,perosiemprebajolamisma
basetecnológica.Portanto,estemanualesválidotantosiquieresconocerAngular2oAngular4olasque
vengan,yaqueelframeworkensísiguemanteniendosusmismasbases.
Encuentrasestemanualonlineen:
http://desarrolloweb.com/manuales/manual-angular-2.html
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 3 de 113
Autoresdelmanual
Lassiguientespersonashanparticipadocomoautoresescribiendoartículosdeestemanual.
MiguelAngelAlvarez
MiguelesfundadordeDesarrolloWeb.comylaplataformadeformaciónonline
EscuelaIT.Comenzóenelmundodeldesarrollowebenelaño1997,
transformandosuhobbyensutrabajo.
AlbertoBasalo
AlbertoBasaloesexpertoenAngularyotrastecnologíasbasadasenJavascript,
comoNodeJSyMongoDB.EsdirectordeÁgoraBinaria,empresadedicadaal
desarrollodeaplicacionesyalaformaciónatravésdeAcademiaBinaria.
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 4 de 113
IntroducciónaldesarrolloconAngular
EnestaprimerapartedelmanualvamosadarlosprimerospasosparadesarrollaraplicacionesconAngular.
Veremoscómocrearelesqueletodelaaplicaciónbásicayconoceremoslosprincipalescomponentesde
todoproyecto.
IntroducciónaAngular
QuéesAngular.PorquésehadecididoescribirdesdeceroelpopularframeworkJavascriptyqué
necesidadesycarenciasresuelveconrespectoasuantecesor.
Angular2hacambiadotantoquehastaelnombreesdistinto.Loconocíamoscomo"AngularJS"yahoraes
sólo"Angular".Nodejadeserunaanécdotaquehayaneliminadoel"JS"hastadelnombredeldominio,
peroesrepresentativo.NoporqueahoraAngularnoseaJavascript,sinoporqueesevoluciónradical.
Angular2esotroframework,nosimplementeunanuevaversión.AlosquenoconocíanAngular1éstoles
seráindiferente,perolosqueyadominabanesteframeworksídebenentenderqueelconocimientoque
necesitanadquirirespocomenosquesicomenzasendesdecero.Obviamente,cuantamásexperienciaenel
desarrollosetenga,mássencilloserálanzarseausarAngular2porquemuchascosassonarándeantes.
EnesteartículoencontrarásunpocodehistoriarelacionadaconAngular1y2,juntoconlosmotivospor
losqueAngular2esotroframeworktotalmentenuevo,querompecompatibilidadhaciaatrás.
Nota:Cabedecirque,aunqueenesteartículonosrefiramosconstantementeaAngularcomoAngular
2,locorrectoesnombrarlosimplemente"Angular".Dehecho,laversión4olapróximaversión5sigue
llamándose"Angular",asecas.EnestosmomentosAngularsehaacogidoalversionadosemántico,por
loqueelnúmerodelaversiónimportamenos,yaquesiempresemantieneelnombredelframework
como"Angular"ylabasetecnológicasiguesiendolamisma.Loqueaprendasenestemanualaplicaa
Angular2,4,5...yenadelante.
RetosynecesidadesdelanuevaversióndeAngular
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 5 de 113
Desdesucreaciónhaceyamásde4años,Angularhasidoelframeworkpreferidoporlamayoríadelos
desarrolladoresJavascript.Esteéxitohaprovocadoquelosdesarrolladoresquieranusarelframeworkpara
másymáscosas.
DeserunaplataformaparalacreacióndeWebApps,haevolucionadocomomotordeunaenorme
cantidaddeproyectosdelámbitoempresarialydeahíparaaplicacionesenlaWebMobileHíbrida,llevando
latecnologíaallímitedesusposibilidades.
EselmotivoporelquecomenzaronadetectarseproblemasenAngular1,onecesidadesdondenose
alcanzabaunasoluciónalaalturadelodeseable.Sonlassiguientes.
Javascript:Paracomenzarencontramosproblemasenlacreacióndeaplicacionesdebidoalpropio
Javascript.Esunlenguajeconcarácterdinámico,asíncronoydecomplicadadepuración.Alsertan
particularresultadifíciladaptarseaél,sobretodoparapersonasqueestánacostumbradasamanejar
lenguajesmástradicionalescomoJavaoC#,porquemuchascosasqueseríanbásicasenesoslenguajesno
funcionanigualmenteenJavascript.
Desarrollodelladodelcliente:YasabemosqueconAngulartellevasalnavegadormuchaprogramación
queantesestabadelladodelservidor,comenzandoporelrenderizadodelasvistas.Estohacequesurjan
nuevosproblemasydesafíos.Unodeelloseslasobrecargaenelnavegador,haciendoquealgunas
aplicacionesseanlentasusandoAngular1comomotor.
Porotrapartetenemosunimpactonegativoenlaprimeravisita,yaquesetienequedescargartodoel
códigodelaaplicación(todaslaspáginas,todaslasvistas,todaslasrutas,componentes,etc),quepuede
llegaratenerunpesodemegas.
Nota:Apartirdelasegundavisitanoesunproblema,porqueyaestándescargadoslosscriptsy
cacheadosenelnavegador,peroparaunvisitanteocasionalsíquerepresentauninconvenientegrande
porquenotaquelaaplicacióntardaencargarinicialmente.
LosintentosdeimplementarLazyLoad,ocargaperezosa,enelframeworkensuversión1.xnofueronmuy
fructíferos.Loidealseríaquenofuesenecesariocargartodatuaplicacióndesdeelprimerinstante,peroes
algomuydifícildeconseguirenlaversiónprecedenteporelpropioinyectordedependenciasdeAngular
1.x.
OtrodelosproblemastradicionalesdeAngulareraelimpactonegativoenelSEO,producidoporun
renderizadoenelladodelcliente.ElcontenidoseinyectamedianteJavascriptyaunquesedicequeGoogle
haempezadoatenerencuentaesetipodecontenido,lasposibilidadesdeposicionamientodeaplicaciones
Angular1eranmuchomenores.Nuevamente,debidoalatecnologíadeAngular1,eradifícildesalvar.
SolucionesimplementadasenelnuevoAngular2
Todosesosproblemas,difícilesdesolucionarconlatecnologíausadaporAngular1,hansidolosquehan
impulsadoasuscreadoresadesarrollardesdecerounanuevaversióndelframework.Lanuevaherramienta
estápensadaparadarcabidaatodoslosusosdadosporlosdesarrolladores,llevaraJavascriptaunnuevo
nivelcomparablealenguajesmástradicionales,siendoademáscapazderesolverdeunamaneraadecuada
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 6 de 113
lasnecesidadesyproblemasdelaprogramacióndelladodelcliente.
EnlasiguienteimagenpuedesveralgunasdelassolucionesaportadasenAngular2.
TypeScript/Javascript:ComobasehemospuestoaJavascript,yaqueeseliniciodelosproblemasde
escalabilidaddelcódigo.Ayudapocoadetectarerroresyademásproduceconfacilidadsituacionespoco
deseables.
Nota:ConECMAscript6yamejorabastanteellenguaje,facilitandolalegibilidaddelcódigoy
solucionandodiversosproblemas,perotodavíaseleexigemás.YapuestosanousarelJavascriptque
entiendenlosnavegadores(ECMAscript5),insertandolanecesidaddeusaruntranspiladorcomoBabel,
podemossubirtodavíaunpocodenivelyusarTypeScript.
Angular2promueveelusodeTypeScriptasusdesarrolladores.Elpropioframeworkestádesarrolladoen
TypeScript,unlenguajequeagregalasposibilidadesdeES6yelfuturoES7,ademásdeuntipadoestáticoy
ayudasdurantelaescrituradelcódigo,elrefactoring,etc.perosinalejartedelpropioJavascript(yaqueel
códigodeJavascriptescódigoperfectamenteválidoenTypeScript).
LasugerenciadeusarTypeScriptparadesarrollarenAngularescasiunaimposiciónporquela
documentaciónylosgeneradoresdecódigoestánpensadosenTypeScript.Sesuponequeenfuturo
tambiénestarándisponiblesparaJavascript,perodemomentonoesasí.Detodosmodos,parala
tranquilidaddemuchos,TypeScriptnoagregamásnecesidaddeprocesamientoalasaplicacionescon
Angular2,yaqueestelenguajesolamenteloutilizasenlaetapadedesarrolloytodoelcódigoqueseejecuta
enelnavegadoresalfinalJavascript,yaqueexisteunatranspilaciónprevia.
Nota:PuedessabermássobreestesupersetdeJavascriptenelartículodeintroducciónaTypeScript.
LazySPA:AhoraelinyectordedependenciasdeAngularnonecesitaqueesténenmemoriatodaslasclases
ocódigodetodosloselementosqueconformanunaaplicación.Enresumen,ahoraconLazySPAel
frameworkpuedefuncionarsinconocertodoelcódigodelaaplicación,ofreciendolaposibilidaddecargar
másadelanteaquellaspiezasquenonecesitantodavía.
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 7 de 113
RenderizadoUniversal:AngularnacióparahacerwebyrenderizarenHTMLenelnavegador,peroahora
elrenderizadouniversalnospermitequenosolosepuedarenderizarunavistaaHTML.Graciasaésto,
alguienpodríaprogramarunaaplicaciónyqueelrenderizadosehaga,porejemplo,enotrolenguajenativo
paraundispositivodado.
OtracosaquepermiteelrenderizadouniversalesqueseuseelmotorderenderizadodeAngulardellado
delservidor.Esunadelasnovedadesmásinteresantes,yaqueahorapodrásusarelframeworkpara
renderizarvistasdelladodelservidor,permitiendounmejorpotencialdeposicionamientoenbuscadoresde
loscontenidosdeunaaplicación.Estamismanovedadtambiénpermitereducirelimpactodelaprimera
visita,yaquepodrástenervistas"precocinadas"enelservidor,quepuedesenviardirectamentealcliente.
DataBindingFlow:UnodelosmotivosdeléxitodeAngular1fueeldatabinding,peroésteteníaun
costeentiempodeprocesamientoenelnavegador,quesibiennopenalizabaelrendimientoentodaslas
aplicacionessíeraunproblemaenaquellasmáscomplejas.Elflujodedatosahoraestámuchomás
controladoyeldesarrolladorpuededireccionarlofácilmente,permitiendooptimizarlasaplicaciones.El
resultadoesqueenAngular2lasaplicacionespuedenllegaraserhasta5vecesmásrápidas.
Componentes:LaarquitecturadeunaaplicaciónAngularahoraserealizamediantecomponentes.Eneste
casonosetratadeunanovedaddelaversión2,yaqueenlaversióndeAngular1.5yaseintrodujoel
desarrollobasadoencomponentes.
Sinembargo,lacomponetizaciónnoesalgoopcionalcomoenAngular1.5,sinoesunaobligatoriedad.Los
componentessonestancos,nosecomunicanconelpadreanoserquesehagaexplícitamentepormediode
losmecanismosdisponibles,etc.Todoestogeneraaplicacionesmásmantenibles,dondeseencapsulamejor
lafuncionalidadycuyofuncionamientoesmásprevisible.Ahoraseevitaelaccesouniversalacualquiercosa
desdecualquierpartedelcódigo,víaherenciaocosascomoel"RootScope",quepermitíaenversiones
tempranasdeAngularmodificarcualquiercosadelaaplicacióndesdecualquiersitio.
Evolucióndelasversiones1y2deAngular
LasversionesdeAngularJS1.xsiguenvivasycontinuarándandosoportedesdeelequipodeAngular.Por
tanto,seprevéquedespuésdelaactual1.5seguiránlanzandoactualizaciones,nuevasversiones,etc.
LanovedadesqueahoracomienzaenparalelolavidadeAngular2yseguiráevolucionandoporsucamino.
Obviamente,laprimeranoticiaqueesperamostodosesquesepresentelaversióndefinitiva(tenencuenta
queenelmomentodeescribirestaslíneasAngular2estásoloenversionesRC,ReleaseCandidate).
Deestemodo,debequedarclaro,paralaspersonasquetenganaplicacionesenAngular1.x,queno
necesitanactualizarlasenunafechadeterminada.Todavíaexisteunbuentiempopordelanteenelquesus
proyectosvanaestarperfectamentesoportadosyelcódigodelasaplicacionesperfectamenteválido.
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 8 de 113
Hananunciadoademásqueenalgúnmomentohabráalgúnsistemaparahacerelupgradedelasaplicaciones
deAngular1.xala2.x.EstopodríapermitirInclusounaconvivencia,enunamismaaplicación,departes
desarrolladasconAngular1yotrasconlaversión2.Lafechadelanzamientodeesehipotético
"ngUpgrade"estásinconfirmaryobviamentetampocoserámagia.Veremosenelpróximopróximoañolo
quesucede,unavezqueesaevolucióndelasversiones1y2esténconviviendo.
Conclusión
SeesperaunfuturomuyprometedoraAngular2.Susnovedadessonimportantesypermitiránafrontarel
futurosobreunabasetecnológicacapazderesolvertodaslasnecesidadesyretosactuales.EnelManualde
Angularestaremosexplicandoenlospróximosmesescómousaresteframeworkparadesarrollartodotipo
deaplicacionesbasadasenJavascript.SiademásquieresaprenderyamismoAngular2,tutorizadopor
nosotrosterecomendamostambiénelcursocompletodeAngular2queencuentrasenEscuelaIT.
ParaaqueldesarrolladorqueempiezadesdeceroenAngular2seráununbonitocaminoquelepermitirá
crecerprofesionalmenteyampliarseriamentesuscapacidadesyelrangodeproyectosqueseacapazde
acometer.Elrecorridopuedeserdifícilalprincipio,perolarecompensaserágrande.
Porsuparte,quienyatengaexperienciaenAngular1.xsiempreleserápositiva,sobretodoparalosque(a
partirdela1.5)comenzaronausarcomponentes.AunqueenAngular2cambielamaneraderealizarlas
cosas,leresultarátodomásfamiliaryportantosucurvadeaprendizajeserámássencilla.
EsteartículoesobradeAlbertoBasalo
Fuepublicadoporprimeravezen09/06/2016
Disponibleonlineenhttp://desarrolloweb.com/articulos/introduccion-angular2.html
AngularCLI
QuéesAngularCLI,elintérpretedelíneadecomandosdeAngular2quetefacilitaráeliniciode
proyectosylacreacióndelesqueleto,oscaffolding,delamayoríadeloscomponentesdeuna
aplicaciónAngular.
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 9 de 113
DespuésdelaintroducciónalascaracterísticasdeAngular2delpasadoartículo,enestaocasiónte
presentamosunaintroducciónAngularCLI,unadelasherramientasesencialesparadesarrollarconel
nuevoframeworkAngular.Esunpasoesencialynecesarioantesdecomenzaravercódigo,puestoque
necesitamosestaherramientaparapoderiniciarnuestraprimeraaplicaciónAngular2,4yversiones
venideras.
DebidoalacomplejidaddeldesarrolloconAngular,aunqueelejemploquedeseemosdesarrollarsetratede
unsencillo"Holamundo",comenzarusandoAngularCLInosahorraráescribirmuchocódigoynos
permitirápartirdeunesquemadeaplicaciónavanzadoycapazdefacilitarlosflujosdedesarrollo.Además
nosofreceráunaseriedeherramientasyaconfiguradasylistasparahacertareascomo,depuración,testingo
deploy.Ydichoseadepaso,elCLItambiénnosahorrarácaerenerroresdeprincipiantequenos
provoquenfrustraciónenlosmomentosiniciales.Asíquevamosconello.
Nota:MencionamoslacomplejidaddeldesarrolloconAngularylanecesidaddeusarsuCLI,peroes
queelpropiodesarrolloparalawebsehasofisticadobastante.Necesitamoscompilarotranspilarel
código,gestoresdedependencias,sistemasdeempaquetadoycompactadodecódigo,sistemasquenos
revisenlasintaxisynosayudenaescribiruncódigolimpio,etc.Cadaunadeesastareaslasdebesde
realizarconunaherramientadefinida,peroconfigurarlastodasyconseguirquetrabajenalunísononoes
unatareatrivial.Apartedetiemponecesitarásbastanteexperienciayesalgoquenosiempresedispone.
Porello,lamayoríadelosframeworksactualesofreceninterfacesporlíneadecomandosparahacerlas
másdiversastareas.Portodoello,nohayunframeworkolibreríaquesepreciequenoofrezcasu
propioCLI.
QuéesAngularCLI
DentrodelecosistemadeAngular2encontramosunaherramientafundamentalllamada"AngularCLI"
(CommandLineInterface).Esunproductoqueenelmomentodeescribiresteartículotodavíase
encuentraenfasebeta,peroqueyaresultafundamentalparaeltrabajoconelframework.
AngularCLInoesunaherramientadeterceros,sinoquenoslaofreceelpropioequipodeAngular.En
resumen,nosfacilitamuchoelprocesodeiniciodecualquieraplicaciónconAngular,yaqueenpocos
minutosteofreceelesqueletodearchivosycarpetasquevasanecesitar,juntoconunacantidadde
herramientasyaconfiguradas.Además,durantelaetapadedesarrollonosofrecerámuchasayudas,
generandoel"scaffolding"demuchosdeloscomponentesdeunaaplicación.Durantelaetapade
producciónotestingtambiénnosayudará,permitiendoprepararlosarchivosquedebensersubidosal
servidor,transpilarlasfuentes,etc.
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 10 de 113
Nodeynpm
AngularCLIesunaherramientaNodeJS,esdecir,parapoderinstalarlanecesitaremoscontarconNodeJS
instaladoennuestrosistemaoperativo,algoquepodemosconseguirmuyfácilmenteyendoalapáginade
https://nodejs.orgydescargandoelinstaladorparanuestrosistema.
Ademásseinstalavía"npm".Pornpmgeneralmentenotetienesquepreocupar,puesseinstalaalinstalar
NodeJS.Noobstanteesimportantequeambasversiones,tantoladelaplataformaNodecomoelgestorde
paquetesnpm,seencuentrenconvenientementeactualizados.Enestosmomentoscomorequisitonospiden
tenerNode4osuperior.
Actualizado:Enestosmomentos,septiembrede2017yparaAngularensuversión4,esnecesario
teneralmenosNodeJSversión6.9.xynpm3.x.x.
Nota:PuedessaberlaversióndeNodequetienesinstalada,asícomolaversióndenpmpormediode
loscomandos:
node -v
npm -v
NotienesquesaberNodeparadesarrollarconAngular,perosínecesitastenerloparapoderinstalary
usarAngularAngularCLI,ademásdeunaseriedeherramientasfantásticasparadesarrolladores.
InstalarAngularCLI
Estoloconseguimosdesdeelterminal,lanzandoelcomando:
npm install -g @angular/cli
DuranteelprocesodeinstalaciónseinstalaráelpropioAngularCLIjuntocontodassusdependencias.La
instalaciónpuedetardarvariosminutosdependiendodelavelocidaddetuconexiónaInternet.
Unavezinstaladodispondrásdelcomando"ng"apartirdelcuallanzaráscualquieradelasaccionesquese
puedenhacermediantelainterfazdecomandosdeAngular.Puedescomenzarlanzandoelcomandode
ayuda:
ng --help
Nota:ng(queselee"enyi")eselapelativofamiliarde"Angular"queseconocedesdeeliniciodel
framework.
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 11 de 113
TambiénencontrarásunaexcelenteayudasientrasenlapáginadeAngularCLI,navegandoporsus
secciones,obienenelpropiorepositoriodeGitHubangular-cli.
CrearelesqueletodeunaaplicaciónAngular2
UnodeloscomandosquepuedeslanzarconAngularCLIeseldecreacióndeunnuevoproyectoAngular
2.Estecomandoseejecutamediante"new",seguidodelnombredelproyectoquequeramoscrear.
ng new mi-nuevo-proyecto-angular
Lanzadoestecomandosecrearáunacarpetaigualqueelnombredelproyectoindicadoydentrodeellase
generaránunaseriedesubcarpetasyarchivosquequizásporsunúmerodespistenaundesarrolladorquese
iniciaenAngular.Siesasínotepreocupesporquepocoapoconosiremosfamiliarizandoconelcódigo
generado.
Además,comohemosdicho,seinstalarányseconfiguraránenelproyectounagrancantidadde
herramientasútilesparalaetapadeldesarrollofront-end.Dehecho,grancantidaddelosdirectoriosy
archivosgeneradosalcrearunnuevoproyectosonnecesariosparaqueestasherramientasfuncionen.Entre
otrascosastendremos:
UnservidorparaservirelproyectoporHTTP
Unsistemadelive-reload,paraquecuandocambiamosarchivosdelaaplicaciónserefresqueel
navegador
Herramientasparatesting
Herramientasparadesplieguedelproyecto
Etc.
Unavezcreadoelproyectoinicialpodemosentrarenlacarpetaconelcomandocd.
cd mi-nuevo-proyecto-angular
Unavezdentrodeesacarpetaencontrarásunlistadodearchivosycarpetassimilaraeste:
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 12 de 113
Nota:EstalistadecarpetasyarchivossehaactualizadoalaversióndeAngular4,enseptiembrede
2017.Connuevasversionesdelframeworknospodemosencontrarconligerasdiferenciasdelcontenido
delaaplicaciónbásicagenerada.Enprincipionodeberíapreocuparnosdemasiado,puestoqueaveces
sereorganizanlascosasoseusandependenciasdistintasquenoalteranmuchoelfuncionamientoolas
prácticasnecesariasparaeldesarrolloconAngular.
Servirelproyectodesdeunwebserver
AngularCLIllevaintegradounservidorweb,loquequieredecirquepodemosvisualizaryusarelproyecto
sinnecesidaddecualquierotrosoftware.Paraservirlaaplicaciónlanzamoselcomando"serve".
ng serve
Esolanzaráelservidorwebylopondráenmarcha.Además,enelterminalveráscomosalidadelcomando
larutadondeelservidorestáfuncionando.Generalmenteseráalgocomoesto(perotesugerimosverificar
elpuertoenlasalidadetuterminal):
http://localhost:4200/
Enlasiguienteimagenveslasalidadelterminalnuestro.
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 13 de 113
Podríasmodificarelpuertoperfectamentesilodeseas,simplementeindicandoelpuertodeseadoconla
opción--port:
ng serve --port 4201
UnavezhayasabiertoennavegadoryaccedidoalaURLdelocalhost,conelpuertoindicado,verásla
pantalladeiniciodelaaplicaciónqueseacabadecrear.Tendráunaspectosimilaraldelasiguienteimagen
(tenencuentaqueestapáginaessolounaespeciede"holamundo"yquesuaspectopuedecambiar
dependiendodelaversióndeAngularqueestésusando.
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 14 de 113
Scriptsdenpm
Paraquiennolosepa,npmesel"NodePackageManager",elgestordepaquetesdeNodeJS.ElCLIde
Angularlohemosinstaladovíanpm.NuestrapropiaaplicaciónAngularsepuedegestionarvíanpm,para
instalarsusdependencias.IremosconociendolasmecánicasenelManualdeAngular,noobstante,
queremosdetenermosahablardeunaherramientadeutilidadalaquepuedessacaryamismoalgodevalor:
losscriptsdenpm.
Losscriptsdenpmsoncomosubcomandosquenpmteaceptaparaautomatizardiferentestareas.Éstosse
definenenelarchivo"package.json",enlasección"scripts".
Nota:"package.json"esunaespeciederesumendelascosasquesehaninstaladoenunproyectovía
npm.NuestraaplicaciónAngularreciéninstaladatieneunarchivopackage.jsonquepuedesabrirpara
darunprimervistazo.Enunarchivopackage.jsonencontramosdiversascosas,comoelnombredel
proyecto,lalicencia,autores,lasdependenciasdeunproyecto,tantolasqueimportanparalafasede
desarrollocomoparaelproyectoengeneral.EstearchivotieneformatoJSON,porloqueesunsimple
textoplanoquenotecostarádeleer.
Comoscriptsdenpmennuestroproyectoreciencreadoencuentrasvariasalternativascomo"start",
"build","test",etc.Esosscriptssepuedenponerenmarchadesdelaconsola,medianteelcomando"npm",
porejemplo,paralanzarelscript"start",tienesqueescribirelcomandodeconsola:
ng start
Enelarchivopackage.jsonencuentraselcomandoqueseejecutaráalhacercadaunodeestosscriptsnpm.
Porejemplo"start"loqueprovocaesqueselanceelcomando"ngserve".Porlotantoloscomandos"npm
start"o"ngserve"enprincipiosonequivalentes.Sinembargo,nosotrospodemosmodificarlosscriptsnpm
paraajustarlosanuestrasnecesidades,oinclusocrearnuevoscomandosnpm.Paraprobarsimplemente
vamosaponer"--o"alfinaldelcomandocorrespondiendeconelscript"start".Este"--o"loquehacees
que,aliniciarseelservidorparacorrerlaaplicaciónAngular,seabraelnavegadordirectamenteynosla
muestre.
"scripts": {
"ng": "ng",
"start": "ng serve --o",
[...]
}
Ahora,alhacerun"npm start"observaráscómoseiniciaelservidorweb,nosindicalaURLdondeestá
disponible,peronosabreelnavegadorautomáticamentemostrandoesaURL.Asíteahorraseltrabajode
lanzartúmismoelbrowseryescribiramanoladireccióndelservidorquesehaabiertoparaservirnuestra
appdeAngular.
ProblemaAngularCLIconBroccolienWindows
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 15 de 113
ElproblemamástípicoquenospodemosencontraralusarAngularCLIesquenotengamospermisosde
administrador.Alintentarponerenmarchaelservidorrecibirásunerrorcomoeste:
TheBroccoliPlugin:[BroccoliTypeScriptCompiler]failedwith:operationnotpermitted.
EsmuysencillodesolucionarenWindows,yaquesimplementenecesitamosabrirelterminalenmodo
administrador(botónderechosobreeliconodelprogramaqueusesparalíneadecomandosy"abrircomo
administrador".EsopermitiráqueAngularCLIdispongadelospermisosnecesariospararealizarlastareas
querequiere.
ACTUALIZACIÓN:EstolohancambiadoenunaversiónbetadeAngularCLI(Beta6),porloqueyano
hacefaltaprivilegiosdeadministradorparausarlasherramientasdelíneadecomandosdeAngular2.
EnLinuxoMac,siteocurrealgosimilar,simplementetendríasquelanzarloscomandoscomo"sudo".
AngularCLItienemuchomás
EnestapequeñaintroducciónsolotehemosexplicadocómoiniciarunnuevoproyectodeAngular2y
cómoservirlodespuéspormediodelcomandoserve.PerolociertoesquedetrásdeAngularCLIhay
muchasotrasinstruccionesdegranutilidad.Principalmente,comohemoscomentado,encontrarásunagran
cantidaddecomandosquepermitencrearelesqueletodecomponentes,directivas,servicios,etc.
AmedidaquevayamosadentrándonoseneldesarrolloconAngular2iremosaprendiendodeunaforma
sencillayprácticatodaslasposibilidadesquepermiteestaherramienta.Demomentoterecomendamos
documentarteenelmencionadorepositoriodeGithub.
EsteartículoesobradeAlbertoBasalo
Fuepublicadoporprimeravezen14/06/2016
Disponibleonlineenhttp://desarrolloweb.com/articulos/angular-cli.html
AnálisisdelascarpetasdeunproyectobásicoconAngular
Angular2exigeunmarcodetrabajomásconcretoyavanzado.Vemoslosarchivosycarpetasque
noshacenfaltaparacomenzarunproyectobásico.
EnelpasadoartículoabordamoslaherramientaAngularCLIyahoravamosaintroducirnosenelresultado
queobtenemosmedianteelcomando"ngnew",quevimosservíaparagenerarelesqueletobásicodeuna
aplicaciónAngular2.
Noobstante,antesdeentrarenmateria,vamosatraerdospuntosinteresantes.Unodeellosesuna
reflexiónpreviasobrelacomplejidaddeunproyecto"vacío"paraunaaplicaciónAngular2.Elotroesuna
delaspreguntastípicasquesehacencuandounapersonaseiniciaconcualquierherramientanueva:el
editorqueserecomiendausar.
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 16 de 113
Profesionalización
TodaslasmejorasquenosofreceAngular2tienenuncosteaniveltécnico.Anteriormente(versiones1.x)
podíamoscomenzarunaaplicacióndeAngularconuncódigodeiniciomuysencilloysinnecesidadde
configurardiversasherramientasfrontend.BásicamentepodíamosenlazarAngulardesdesuCDNyconun
scriptmuyelementalempezarausarlo.
Estoyanoesasí.ConAngular2elnúmerodepiezasquenecesitamosintegrar,inclusoenaplicacionestan
sencillascomoun"holamundo",esmuchomayor.
Enaplicacionesgrandes,dondeexistíaunentornobiendefinidoporpartedelequipodedesarrollodeesa
aplicación(linter,transpiler,loader,tester,deployer…)seequilibra.Esdecir,Angularnonosexigenada
nuevoqueyanoestuvieranusandoequiposdedesarrollodeaplicacionesgrandes.Perolociertoesque
aplicacionespequeñastendránbastantemáscomplejidad.Todoestonosllevaaquedesarrolladores
ocasionalesencontraránmásdifícilelusodelframeworkensuspasosiniciales,peroelesfuerzosinduda
merecerálapenaporquelospondráaunnivelmuysuperioryesoredundaráensubeneficioprofesional.
¿QuéeditordecódigousarconAngular2?
Sepuedeusarcualquiereditordecódigo.EsunaaplicaciónHTMLyJavascript/TypeScript,porloque
puedesusarcualquIereditordelosquevienesusandoparacualquieradeestoslenguajes.
Comorecomendaciónsesugiereusaruneditorligero,peroquetefacilitelaprogramación.Entrelosque
encontramosdecódigolibreygratuitosparacualquierusoestánBrackets,AtomoVisualStudioCode.Éste
últimoesquizáselmásindicado,porqueyavieneconfiguradoconunaseriedeherramientasútilesyclave
paradesarrollarconAngular2comoesel"intellisense"deTypeScript.Detodosmodos,atravésdeplugins
podráshacerquetueditorpreferidotambiénseacapazdemostrartelasayudasentiempodeprogramación
delcompiladordeTypeScript.
ArchivosycarpetasconunproyectodeAngular2.1yAngular4
Comenzaremosexplicandolosarchivosycarpetasqueencuentrasenunaaplicaciónreciéncreadaconel
AngularCLI,talcomoloencontrarássiusasAngular4,yenversionesmásadelantadasdeAngular2.Más
adelanteenestemismoartículoexplicaremostambiéncarpetasqueaparecíanenlasprimerasversionesde
Angular2,quenosonexactamentelosmismos.Elmotivoprincipaldeestasdiferenciasesqueeltooling
queseusaenAngularcambiópocodespuésdeliberarlaversión2,porejemploconlaincorporaciónde
WebPack.ConellotambiénlaestructuradelascarpetasbásicasdeunproyectoAngularcambió.Noesuna
diferenciamuygrande,ycreemosqueesútilquemantengamosenelmanualambasalternativas.
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 17 de 113
Archivossueltos:
Encontrarásvariosarchivossueltosenlacarpetaraízdetuproyecto.Teseñalamosalgunosimportantesque
debesconocer:
index.htmlEstearchivoesinformaciónbásicadelproyectoreciéncreado.Tepuededarunaideainicialde
quéesloqueencontrarásenestascarpetasycómousarelproyecto.Complementarásindudalas
explicacionesdeestemanualdeAngular.EncontrarásalgunoscomandosexplicadosdelCLI,como"ng
serve"elcuályahemostratado,paraservirelproyecto.Tambiéncomentaráquetienesquehacerpara
realizarelbuild,comando"ngbuild"yllevaraproducciónunaaplicación.
.angular-cli.jsonEsunarchivooculto(enLinuxoMac,puescomienzapor".")enelquesealmacenan
configuracionesdelCLIdeAngular.
package.jsonEsteeselarchivoqueresumelasdependenciasdelproyecto,laslibreríassobrelasquenos
apoyamos,quesegestionanpormediodenpm.
tslint.jsonEstearchivosirveparaconfigurarellinter,elprogramaquenosalertarácuandotengamos
problemasdeestiloenelcódigo.
.editorconfigEsteesunarchivoquesirveparadefinirlaconfiguraciónparaeleditordecódigoque
estemosutilizando.Permitecentralizarlaconfiguración,demodoqueseacomúnparatodoslos
desarrolladoresquevayanatrabajarenelproyecto.
Carpetasrc
Eslacarpetadondeestánlasfuentesdelproyecto.Estacarpetaeslaqueusaremosparadesarrollarla
aplicaciónydondeiremoscolocandocomponentesyotrotipodeartefactosnecesariosparaponeren
marchanuestrasideas.
Entrode"src"encuentrasmuchosarchivosqueseguramenteteseránfamiliares,comoelindex.html,que
hacederaízdelproyecto.Esinteresantequeabrasesearchivoparacomprobarcómoeslaraízdeuna
aplicaciónAngular.Tedeberíallamarlaatenciónelcódigoqueencontrarásenelbody:
<app-root></app-root>
Ese"app-root"eselcomponenteraízdelaaplicación.Eneldesarrollobasadoencomponentesesun
patrónnormalquetodalaaplicaciónseconstruyaenuncomponenteprincipal,delquecolgarátodoun
árboldecomponentesespecializadosenhacercadaunadelascosasnecesarias.
Nota:EnAngularsedesarrollaenbaseacomponentes.Sinuncahasconocidoesteparadigmaquizáste
parezcaextraño,peropocoapocoloiremosentendiendotodoyapreciandolasventajas.Obviamente,
nolopodemosexplicartodoenunartículo,asíquetepedimosunpocodepaciencia.
Otrodelosdetallesqueencontrarásen"src"sonvariosarchivosconextensión".ts".Sonarchivoscon
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 18 de 113
códigoTypeScript.RecuerdaqueenAngularseprogramausandoTypeScriptyqueenelprocesode
transpiladodelaweb,realizadoporWebPack,esecódigopasaráatraducirseaJavascript.Nohacefaltaque
tepreocupesmuchotodavía,puesyaloestudiaremosconcalma.Puedesabrirsiquiereselmain.ts,queesel
códigodeTypeScriptprincipaldelaaplicación,elpuntodeiniciodeejecución,aunqueyateadvertimosque
estearchivoprácticamentenolotendremosquetocar.
Dentrode"src"encontrarástambiénunacarpetallamada"app",quecontieneelcódigodelcomponente
principal,queestádivididoenvariosarchivos.Siabreselarchivo".html"veráselcódigodepresentación
delcomponente,queeselquesemuestracuandosevisualizalaaplicaciónreciéncreada.
Enlacarpeta"src"haymuchosotrosarchivos,peronoqueremosaburrirtecontodoslosdetalles,pueslos
tendremosqueanalizarpocoapoco.
Carpetanode_modules
Eslacarpetadondenpmvacolocandotodaslasdependenciasdelproyecto,esdecir,elcódigodetodaslas
libreríasocomponentesqueestemosusandoparabasarnoseneldesarrollodeunaaplicación.Porejemplo,
elpropioAngularesunadependencia.
Carpetae2e
Enestacarpetasecolocanlosarchivosparalarealizacióndelaspruebas"endtoend".
Otrascarpetas
Amedidaquetrabajespodrásencontrarenelproyectocarpetascomo"test"o"dist",pararealizareltesto
paraalmacenarlosarchivoslistosparaproducción.Sigueleyendolascarpetasdisponiblesenelproyecto
Angular2.0paramásinformación.
ArchivosycarpetasdelproyectoconAngular2.0
Impactaunpocoque,reciéncreadounproyectoparaAngular2pormediodeAngularCLI,veamosenla
carpetadearchivosvariassubcarpetas,yvariasdeellasconelcontenidodecientosdeficheros.No
obstante,notodoescódigodetuaplicación,sinomuchasvecessoncarpetasparacrearlainfraestructurade
todoeltoolingNodeJSincluidoparagestionarunaaplicaciónAngular2.
Ahoraconoceremoslaspartesquenoshacenfaltaparacomenzar,aunquesinentrarendemasiadosdetalles.
Todoslosarchivosdelraíz:Seguroquemuchosdeloslectoresreconocenmuchosdelosarchivosque
haydentro,comopackage.json(descriptordedependenciasnpm)o.gitignore(archivosycarpetasquegit
deberíaignorardeesteproyectocuandoseañadaalrepositorio).Enresumen,todoloqueencontraremos
enestaraíznosonmásquearchivosquedefinennuestroproyectoyconfiguranelentornoparadiversas
herramientas.
Nota:Observarásquenohayunindex.html,porqueestanoeslacarpetaraízdelosarchivosquese
debenservirporelservidorweb.
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 19 de 113
src:Eslacarpetamásinteresanteparaticomodesarrollador,yaqueesellugardondecolocaráselcódigo
fuentedetuproyecto.Enrealidadmásenconcretolacarpeta"app"queencontrarásdentrode"src"es
dondetienesqueprogramartuaplicación.Observarásqueyavienecondiversoscontenidos,entreotras
cosaselindex.htmlquedebeservircomopáginadeinicio.Noobstante,noesexactamenteeldirectorioraíz
depublicación,porquealdesplegarelproyectolosresultadosdecompilartodoslosarchivossellevaránala
carpeta"dist".
Enlacarpetasrcesdondevasarealizartodotutrabajocomodesarrollador.Seguramenteotrosmuchos
archivosteresultenfamiliares,comoelfavicon.ico.
Verásademásvariosarchivos.ts,quesoncódigofuenteTypeScript.Comoquizássepas,losarchivos.ts
soloexistenenlaetapadedesarrollo,esdecir,enelproyectoqueelnavegadordebeconsumirno
encontrarásarchivos.ts,básicamenteporqueelnavegadornoentiendeTypeScript.Esosarchivossonlos
quesecompilaránparaproducirelcódigo.jsquesíentiendaelnavegador.
Nota:SitodavíateencuentrasreticentealusodeTypeScriptnotepreocupes,yaquecualquiercódigo
JavascriptquepongaseneseficheroescódigoTypeScriptválido.Portantotúpodríasperfectamente
escribircualquiercódigoJavascriptdentrodelosarchivos.tsytodoiráperfectamente.Siademás
conocesalgodeTypeScriptyloquieresusarparafacilitartelavidaentiempodedesarrollo,tantomejor
parati.
dist:Eslaversióndetuaplicaciónquesubirásalservidorwebparahacerpúblicoelproyecto.Endist
aparecerántodoslosarchivosqueelnavegadorvaanecesitarynuncacódigofuenteenlenguajesno
interpretablesporél.(Observaquenohayarchivos.tsdentrodedist).Ojo,puesmuyprobablementetengas
queiniciarelservidorwebintegradoenAngularCLIparaqueaparezcalacarpeta"dist"eneldirectoriode
tuproyecto.PuedesobtenermásinformaciónsobrecómolanzarelservidorwebenelartículodeAngular
CLI.
Public:Esdondecolocaslosarchivosestáticosdelproyecto,imágenesycosassimilaresqueseconocen
habitualmentecomo"assets".Estosarchivostambiénsemoverána"dist"paraqueesténdisponiblesenla
aplicaciónunavezsubidaalservidorwebdesdedondesevaaacceder.
e2e:Esparaeldesarrollodelaspruebas.Vienede"endtoend"testing.
node_modules:Sonlosarchivosdelasdependenciasquemantenemosvíanpm.Portanto,todaslas
libreríasquesedeclarencomodependenciasenelarchivopackage.jsondebenestardescargadosenesta
carpetanode_modules.Estacarpetapodríahaberestadodentrodesrc,peroestácolgandodelaraízporque
valetantoparalaspruebas,comoparalaaplicacióncuandolaestásdesarrollando.
tmp:Esunacarpetaquenotocaremos,conarchivostemporalesquegeneraráAngularCLIcuandoesté
haciendocosas.
Typings:EstosondefinicionesdetiposusadosporlaslibreríasqueusaunproyectoenAngular2.Estos
tipostesirvenparaqueeleditor,graciasaTypeScript,puedainformarteconel"intellisense"enelactode
escribircódigo,sobrelascosasrelacionadasconesaslibrerías.
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 20 de 113
Demomentoesoestodo,esperamosqueestavistadepájarotesirvadeutilidadparareconocerla
estructurabásicadeunproyectoadesarrollarconAngular2.Enelsiguienteartículoentraremosendetalle
yasobreelcódigo,analizandopordentroalgunasdeestascarpetasyarchivosgeneradosdesdeAngularCLI
yrealizandonuestrasprimeraspruebas.
EsteartículoesobradeAlbertoBasalo
Fuepublicadoporprimeravezen20/06/2016
Disponibleonlineenhttp://desarrolloweb.com/articulos/analisis-carpetas-proyecto-angular2.html
VistadepájaroalcódigodeunaaplicaciónAngular(4)
UnaaproximaciónaloselementosprincipalesqueencontramosenunaaplicaciónAngular,
versión4,entendiendoelcódigo.
Enelcapítuloanteriorofrecimosunadescripcióngeneraldelaestructuradecarpetasdeunaaplicación
Angular,juntoconalgunosdesusprincipalesarchivos.Ahoravamosaintroducirnosenelcódigoytratar
deentendercómoestáconstruida,almenoscuáleselflujodeejecucióndelosarchivosquevamosa
encontrar.
Laaplicaciónquevamosaradiografiareslaqueconseguimosmedianteelcomando"ngnew"delCLI.
Esperamosqueyatengastuaplicacióngenerada.Sinoesasí,terecomendamosanteslalecturadelartículo
deAngularCLI.Vamosausarlaversión4deAngular,aunqueserviríaparacualquierversióndel
frameworkapartirdela2.
Obviamentenopodremoscubrirtodoslosdetalles,peroesperamosquedeesteartículoteofrezcabastante
luzsobrecómoseejecutanlosarchivosprincipalesdeAngular.Verásqueiremossaltandodeunarchivoa
otro,dentrodelaaplicaciónbásicageneradacon"ngnew",recorriendobásicamenteelflujodeejecución.
Alfinaltendrásunresumencompletodelospasosdeesterecorridoqueesperamostesirvaparaapreciarlo
demanerageneral.
Nota:lociertoesqueesteartículocubreAngulardesdequesepasóaWebpack.Enlasversiones
tempranasdeAngular2,usabanSystemJSparalagestiónycargadedependencias.Elcódigodeuna
aplicaciónusandoesaversiónantiguayaseexplicóenelartículoZambullidaenelcódigodelproyecto
inicialdeAngular2.
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 21 de 113
ArchivoIndex.html
Esdesobrasabidoquelasaplicacioneswebcomienzanporunarchivollamadoindex.html.ConAngular
además,dadoqueseconstruyenpáginasSPA(SinglePageApplication)estodavíamásimportanteel
index.html,puesenprincipioeselarchivoquesirveparamostrarcualquierrutadelaaplicación.
Elindex.htmlennuestraaplicaciónAngular,comocualquierotroarchivodelosqueformanpartedelaapp,
seencuentraeneldirectorio"src".Siloabrespodrállamartelaatenciónalmenosunpardecosas:
AusenciadeJavascript:
NohayningúnJavascriptdeningúntipoincluidoenelcódigo.EnrealidadelcódigoJavascriptquesevaa
ejecutarparainicializarlaaplicaciónesinyectadoporWebpackycolocadoenelindex.htmlcuandola
aplicaciónseejecutaocuandosellevaaproducción.
ElBODYprácticamentevacío:
EnelcuerpodelapáginanoapareceningúnHTML,salvounaetiqueta"app-root".Estaesunaetiquetano
estándar,quenoexisteenelHTML.Enrealidadesuncomponentequemantienetodoelcódigodela
aplicación.
Nota:Deberíamoshacerunstopalanálisisdelcódigoparanombrarla"Arquitecturadecomponentes".
EnAngularyenlamayoríadelibreríasyframeworksactualessehaoptadoporcrearlasaplicacionesen
baseacomponentes.Existeuncomponenteglobal,queeslaaplicaciónenterayasuvezéstesebasaen
otroscomponentesparaimplementarcadaunadesuspartes.Cadacomponentetieneuna
representaciónyunafuncionalidad.Enresumen,lasaplicacionesseconstruyenmedianteunárbolde
componentes,queseapoyanunosenotrospararesolverlasnecesidades.Enelindex.htmlencontramos
loqueseríaelcomponenteraízdeesteárbol.Comenzamosavermásdetallesobreloscomponentesen
elsiguienteartículoIntroducciónaloscomponentesenAngular2.
Archivomain.ts
Comohemosvisto,noexisteunJavascriptdefinidooincluidoenelindex.html,perosíseagregarámás
adelanteparaquelaaplicaciónfuncione.Dehecho,siponeslaaplicaciónenmarchacon"ngserve-o"se
abriráentunavegadory,alverelcódigofuenteejecutadopodrásverquesíhaycódigoJavascript,colocado
antesdecerrarelBODYdelindex.html.
EsecódigoestágeneradoporWebpack,einyectadoalindex.htmlunavezlapáginaseentregaalnavegador.
ElscriptJavascriptqueelnavegadorejecutaráparaponerenmarchalaaplicacióncomienzaporelarchivo
main.ts,queestáenlacarpeta"src".
Nota:PodríallamartelaatenciónquenoesunarchivoJavascriptelquecontieneelcódigodela
aplicación,peroyadijimosenlaIntroducciónaAngular,queesteframeworkestáescritousandoel
lenguajeTypeScript.Enalgúnmomentoesecódigosetraducirá,lógicamente,paraqueseconviertaen
Javascriptentendibleportodoslosnavegadores.EseprocesolorealizaWebpackperorealmenteno
debepreocuparnosmuchoyaqueeselpropioAngularCLIquevaarealizartodaslastareasvinculadas
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 22 de 113
conWebpackyelcompiladordeJavascriptparalatraduccióndelcódigo,demaneratransparenteparael
desarrollador.
Siabreselmain.tsobservarásquecomienzarealizandounaseriede"import",paracargardistintaspiezasde
código.EsosimportsontípicosdeES6,aunqueenestecasotelosofreceelpropioTypeScript,yaqueel
transpiladordeestelenguajeeselquelosconvertiráaunJavascriptentendibleportodoslosnavegadores.
Losimportqueencuentrasloshaydedostipos.
1.-importsdedependenciasalibreríasexternas
Estosimportsoncódigodeotrosproyectos,dependenciasdenuestraaplicación.Estángestionadospor
npmyhansidodeclaradoscomodependenciasenelarchivopackage.jsonquedeberíasconocer.Tienenla
forma:
import { enableProdMode } from '@angular/core';
Enestecasonosfijamosen'@angular/core'queesunadelaslibreríasdependientesdenuestraaplicación,
instaladasvíanpm,cuyocódigoestáenlacarpeta"node_modules".Enesacarpeta,decódigodeterceros,
nuncavamosatocarnada.
2.-Importsacódigodenuestropropioproyecto
Tambiénencontraremosimportsaelementosqueformanpartedelpropiocódigodelaaplicaciónyquepor
tantosípodríamostocar.Losdistinguesporquetienenestaforma:
import { AppModule } from './app/app.module';
Aquínosfijamosenlarutadelmóduloqueseestáimportando'./app/app.module',queesrelativaalpropio
main.ts.
Nota:enlarutaalarchivoqueseestáimportandofaltael".ts",yaqueelarchivoesunTypeScript.Pero
realmentenosedebecolocar,puestoqueesearchivo.tsenalgúnmomentosetraduciráporunarchivo
.js.Paranoliarse,recuerdaquelosimportaarchivosTypeScriptnosecolocalaextensión.
Obviamente,paraprofundizarhabríaqueentenderquéescadaimportdelosquesevanrealizando,los
cualestendremostiempodeanalizarllegadoelmomento.
Ademásdelosimports,queescódigoquesevarequiriendo,hayundetallequeencontramosalfinaldel
fichero:
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 23 de 113
platformBrowserDynamic().bootstrapModule(AppModule)
.catch(err => console.log(err));
Estoeselbootstrap,elarranque,delaaplicación,quepermitedecirleaAngularquétienequehacerpara
comenzaradarvidaalaaplicación.Alinvocaralsistemadearranqueestamosindicandoquémódulo
(AppModule)eselprincipaldelaaplicaciónyelquetieneloscomponentesnecesariosparaarrancar.
Alfinal,elbootstrapprovocaráqueAngularleaelcódigodelmóduloysepaquécomponentesexistenenel
index,paraponerlosenmarcha,provocandoquelaaplicaciónempieceafuncionar,talcomosehaya
programado.
Nota:fíjatequeparaarrancarlaaplicaciónsehaceusodeloselementosquehemosimportadoenlas
líneasanteriores,entreellosplatformBrowserDynamicyAppModule.
Archivoapp.module.ts
Deentretodoslosimportsquesehaceenelmain.tshayunofundamental,quenossirveparatirardelhiloy
verquéesloqueestápasandoporabajo,parahacerposiblequetodocomienceafuncionar.Setratade
app.module.ts,quepodemosconsiderarcomoelmóduloprincipaldelaaplicación.
Enesteficheronosencontramos,comovieneyasiendohabitual,variosimportsdeelementosquevienen
deotrosmódulos,perohayademásdoscosasquepuedenserclaveparaentenderelflujodeejecución.
Importdenuestrocomponenteraíz
Enelmóduloprincipal,app.module.ts,encontramoselimportalcomponenteraízdelaaplicación(esa
etiquetaHTMLno-estándarqueaparecíaenelBODYdelindex).
import { AppComponent } from './app.component';
Estecomponenteesimportanteenestepuntoporqueeselprimeroqueestamosusandoyporqueesel
únicoqueteofrecenyaconstruidoenlaaplicaciónbásicacreadaconelCLIdeAngular.
Alimportarelcomponenteloqueestamosobteniendoesunareferencia"AppComponent",dondeestarála
clasecreadaparaimplementarelcomponente.
Decorador@NgModule
Estaeslaprimeravezquequizásestásconociendolosdecoradores,algoquevienedirectamenteotorgado
porTypeScript.Losdecoradorespermitenasignarmetadataafunciones,clasesuotrascosas.Lasfunciones
decoradorastienenunnombreylasusamosparaasignaresosdatos,quepodríanmodificarel
comportamientodeaquelloqueseestádecorando.
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 24 de 113
EldecoradorcompletoenlaversióndeAngularqueestamosusando(4)eseste:
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule
],
providers: [],
bootstrap: [AppComponent]
})
Comoves,alafuncióndecoradoralaalimentamosconunobjetopasadoporparámetro,enelque
indicamosdiversosdatosútilesparalaclaseAppModule.Estedecoradorseiráeditandoyagregandonuevas
cosasamedidaquevayamosdesarrollando,porloquenosresultarábastantefamiliarapocoque
comencemosadesarrollarconAngular.
Eneldecoradorhayunapropiedadllamada"bootstrap",quecontieneunarrayconloscomponentesque
Angulartienequedarvida,paraconseguirquelascosascomiencenafuncionar:bootstrap:
[AppComponent].EstolediceaAngularquehayenelindex.htmlhayuncomponenteimplementadocon
laclaseAppComponent,quetienequeejecutar.
Componenteraízdelaaplicación
Parallegaralmeollodelcódigo,tenemosqueobservar,aunquetodavíaporencima,elcomponenteraíz.Lo
habíamosusadoenelindex.html:
<app-root></app-root>
Peroechemosunvistazoalcódigodelcomponente.Surutalapuedesdeducirdelimportqueseha
realizadoenelapp.module.ts,osea"src/app/app.component.ts".
Demomentosoloqueremosqueencuentrestusegundodecorador,conelcódigosiguiente.
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
Elselectoroetiquetaqueimplementaestecomponente:"app-root".Justamenteeslaetiqueta
extrañaquehabíaenelindex.html.
Elarchivo.htmlsutemplate:"./app.component.html".
LosestilosCSSqueseusanenelcomponente:"./app.component.css"
Conloqueacabasdever,seráfácilabrirencontrarelarchivodondeestáeltemplate.¿no?Puedesabrirloy
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 25 de 113
veráselcódigoHTMLqueaparecíaalponerenmarchalaaplicación.(Comando"ngserve-o"delCLI)
ResumendelflujodeejecucióndelaaplicaciónbásicaAngular(4)
Somosconscientesquehemosaportadomuchosdatosenesteartículo,quizásdemasiadosparaasimilarlos
enunaprimeralectura.Sitodoesnuevoparatidebedeserunpococomplicadohacerseunesquema
perfectodelfuncionamientodelascosas,asíquevamosapararunmomentopararepasardenuevoelflujo
deejecucióndelcódigo.
1. Enelindex.htmltenemosuncomponenteraízdelaaplicación"app-root".
2. Alservirlaaplicación(ngserve),oalllevarlaaproducción(ngbuild)laherramientaWebpack
generalospaquetes(bundles)decódigodelproyectoycolocaloscorrespondientesscriptsenel
index.html,paraquetodofuncione.
3. ElarchivoporelqueWebpackcomienzaaproducirlosbundleseselmain.ts
4. Dentrodelmain.tsencontramosunimportdelmóduloprincipal(AppModule)ylallamadaal
sistemadearranque(bootstrapModule)enlaquepasamosporparámetroelmóduloprincipaldela
aplicación.
5. Enelmóduloprincipalseimportaelcomponenteraíz(AppComponent)yeneldecorador
@NgModuleseindicaqueestecomponenteformapartedelbootstrap.
6. Elcódigodelcomponenteraíztieneelselector"app-root",queeslaetiquetaqueaparecíaenel
index.html.
7. Eltemplatedelcomponenteraíz,contieneelHTMLquesevisualizaalponerenmarchala
aplicaciónenelnavegador.
Conclusión
Porfinhemosllegadoaseguirlaejecucióndelaaplicación,paraencontrarsucontenido.Seguroque
habiendollegadoaestepuntosentirásunapequeñasatisfacción.Puedesaprendermásdeloscomponentes
enelartículoIntroducciónaloscomponentesenAngular2.
Somosconscientesquemuchodelconocimientohaquedadoenelaireyhaymuchasdudasquequerrás
resolver,peroconloquehemosvistohemosconseguidoelobjetivoplanteado,disponerdeunavistade
pájarodelcódigoqueencuentrasaliniciartuaplicaciónAngular.
PuedescontinuarlalecturadelManualdeAngularparaobtenermásinformaciónsobredecoradores,
componentes,yarranquedelasaplicaciones.
EsteartículoesobradeMiguelAngelAlvarez
Fuepublicadoporprimeravezen05/10/2017
Disponibleonlineenhttp://desarrolloweb.com/articulos/codigo-aplicacion-angular.html
ZambullidaenelcódigodelproyectoinicialdeAngular2
ComenzamosaanalizarelcódigodeunproyectobásicoconAngular2,enlasprimerasversiones,
generadoconAngularCLI.Prestamosalindexdelaaplicaciónyalcomponenteprincipal,que
podremoseditarparacomprobarelfuncionamiento.
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 26 de 113
Enesteartículovamosaanalizarelcódigodelaaplicacióninicialqueseinstalaalhacerunnuevoproyecto
conAngularCLI.TenencuentaqueenartículosanterioresdelManualdeAngular2hemosabordadoyaen
unaprimerainstancialaestructuradecarpetasgeneradaporAngularCLI,ademásdeexplicarcómocrearla
atravésdecomandosdeconsola.
Portanto,noscentraremosenentendercuáleselflujodeejecucióndelcódigo,juntoconlosarchivosque
sevanincluyendoyrecorriendoalejecutarlaaplicación.Obviamente,habrácosasenlasquenopodamos
entrartodavíaenmuchosdetalles,peronohayquepreocuparseporqueseránmateriadeestudioen
sucesivosartículos.
NOTAIMPORTANTE:ElcontenidodeesteartículoaplicaaversionestempranasdeAngular2.
AlPrincipioelsistemaparalagestióndepaquetesydependenciaseraSystemJS.Sinembargo,
actualmenteAngulartrabajaconWebpack.Yaenlaversión2deAngularsemigróaWebpacky
huboalgunoscambiosrelevantesenlamaneradeconstruirselaaplicaciónbásicadeAngularconel
AngularCLI.Esporelloqueelcontenidoseguramentenosearelevanteparati.Sientenderelcódigo
deAngular2oAngular4porfavorleeelartículoVistadepájaroalcódigodeunaaplicación
Angular.Sinembargo,muchosdatosofrecidosenelsiguientetextosiguenteniendovigenciaypueden
aclararpuntosinteresantessobrelaprogramaciónusandoesteframework.
Archivopackage.json
Vamosacomenzarporanalizarestearchivo,yaquemuchascosassondeclaradasinicialmenteenél.Al
analizarestearchivoencontraremoselorigendemuchasdelaslibreríasqueusaAngular2.
Comodebessaber,package.jsonesunarchivoenelquesedeclaranlasdependenciasdeunaaplicación,
gestionadasvíanpm.SucódigoesunJSONenelquesedeclaranvariascosas.
Inicialmentehayqueverlapropiedad"dependencies".EnellaencontraráslalibreríaAngularseparadaen
variosmódulos.Estaesunadelascaracterísticasdelanuevaplataformadedesarrollopromovidapor
Angular2,lamodularizacióndelcódigo.EncontrarásqueunaaplicaciónAngular2necesitayadeentrada
diversosmóduloscomoson"common","compiler","core",etc.
Luegohayunaseriedelibreríasdeterceros,nocreadasdirectamenteporelequipodeAngular,obien
creadasporellosmismosperoconunenfoqueuniversal(capazdeusarseenotrostiposdeproyectos).Son
"es6-shim","rxjs",etc.
Todosestosmódulosantesseincluíanpormediodescripts(etiquetaSCRIPT)enelHTMLdelapágina.
PeroenestaversiónygraciasaAngularCLIyavieneincorporadaunamejormaneradeincluirmódulos
Javascript,pormediode"SystemJS".ObservarásqueelpropioSystemJSestáincluidocomodependencias
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 27 de 113
"systemjs"yconélpodríamosincluirtodotipodecódigo,nosoloJS,sinootrosficherosnecesarioscomo
CSS.
Nota:AldescribirlaestructuradecarpetasdelproyectoAngular2yaexplicamosquetodaslas
dependenciasdepackage.jsontelasinstalanpmenlacarpeta"node_modules".
EntendiendolobásicodeSystemJS
Paracomenzarpornuestroanálisisdelcódigo,vamosaabrirelarchivo"src/index.html".
Comodijimos,lacarpetasrcesdondeseencuentranlasfuentesdetuproyecto.Enellaencontramosun
index.htmlqueeslaraízdelaaplicación.Todoempiezaaejecutarseatravésdeestearchivo.
Tellamarálaatenciónelcódigosiguiente:
{{#each scripts.polyfills}}<script src="{{.}}"></script>{{/each}}
EsecódigohaceunrecorridoporunaseriedelibreríasylasvacolocandodentrodeetiquetasSCRIPTpara
incluirsucódigoenlaaplicación.Demomentoloquedebessabersobreestecódigoesquepormediodeél
secarganlibreríasexternasquenecesitaAngularyquehemosvistodeclaradasenlas"dependencies"del
archivopackage.json.Loquenosinteresasaberesqueasíseestácargando,entreotras,lalibreríaSystemJS.
Ahora,enelfinaldeindex.htmlencontrarásallíunscript.Cuandollegamosaestepunto,SystemJSyaestá
cargadoyenesteScriptserealizaunainicializacióndeestalibreríaparacargarloselementosnecesariospara
comenzaratrabajar:
<script>
System.import('system-config.js').then(function () {
System.import('main');
}).catch(console.error.bind(console));
</script>
Encontramoselobjeto"System",queesunavariableglobaldefinidaporlalibreríaSystemJS.Pormediodel
método"import"consiguecargarmódulos.Apreciarásqueseestácargandoinicialmenteunarchivo
llamado"system-config.js".
Luegovemoselmétodothen()ycatch().Estosmétodoslosdeberíasdereconocer,puessonpertenecientes
aunpatrónbienconocidoporlosdesarrolladoresJavascript,eldepromesas.Elmétodothen()seejecutará
cuandoseterminedecargarelmódulo"system-config.js"yelmétodocatch()seejecutaríaencasoqueno
sehayapodidocargaresearchivo.Graciasathen(),despuésdehabercargado"system-config.js"entonces
secargará"main",queenseguidaveremosquées.
Enestepuntotepreguntarás¿Dóndeestásystem-config.js?.Quizásnoloencuentres,peroveasenlamisma
carpeta"src"elarchivosystem-config.ts.EseesunarchivoTypeScriptquecontieneelcódigodesystem-
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 28 de 113
config.jsantesdetranspilarconelTypeScriptCompiler.
Nota:TypeScriptesunlenguajeparaelprogramador.LoqueusaelnavegadoresJavascript.El
TypeScriptcompilerseencargarádehaceresaconversióndel.tsaun.js.
Elarchivosystem-config.tsgeneralmentenolovasatenerquetocar,porqueAngularCLIteloirá
actualizando.Siloabressindudairásreconociendoalgunaslíneas,cosasquenecesitaráSystemJS.No
vamosaentrarahoraeneldetalle,demomentoquédateconqueescódigogenerado.
Porsupartelareferenciaa"main"queteníamosantesenlosimportdelindex.htmlSystem.import('main'),
esunimport.Noleponennisiquieralaextensióndelarchivo"main.js"yestoesporque"main"esunalias
declaradoenelsystem-config.ts.Fíjateenelcódigodelarchivo,enestaslíneas:
// Apply the CLI SystemJS configuration.
System.config({
map: {
'@angular': 'vendor/@angular',
'rxjs': 'vendor/rxjs',
'main': 'main.js'
},
packages: cliSystemConfigPackages
});
Elobjeto"map"tieneunalistadealiasyarchivosqueseasocian.Siendoque"main"correspondecon
"main.js".Nuevamente,noencontrarásun"main.js"entrelosarchivosdelproyecto,enlacarpeta"src",
porqueloquetendremosesunmain.tsqueluegoseconvertiráenelmain.js.
Ahorapuedesabrirmain.js.VerásquesucódigonuevamentehaceusodeSystemJS,realizandodiversos
imports.EstosimportssoncomolosqueconocesenECMAscript6ybásicamenteloquetetraenson
objetosdediversaslibrerías.
Encontrarásestecódigoenmain.js,oalgosimilar:
import { bootstrap } from '@angular/platform-browser-dynamic';
import { enableProdMode } from '@angular/core';
import { TestAngular2AppComponent, environment } from './app/';
Porejemplo,estásdiciéndolequeimporteelobjeto"bootstrap"delalibrería"@angular/platform-browser-
dynamic".Esalibreríaestádeclaradadentrode"system-config.ts"
Luegoverásotraslíneas,queeselbootstrap,oiniciodelaaplicaciónAngular.Novamosaentrarendetalle,
peroesloequivalenteal"ng-app"quecolocabasantesenelcódigoHTMLdetuindex.Esto,oalgo
parecidoyasepodíahacerconAngular1yseconocíacomoelarranquemanualdeAngular.
Componenteprincipaldeunaaplicación
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 29 de 113
Seguimosanalizandoindex.htmlyencontramosenelcódigo,enelcuerpo(BODY)unaetiquetaquellamará
laatenciónporquenoesdelHTMLtradicional.Eselusodeuncomponenteysucódigoseráalgocomo:
<mi-nombre-proyecto-app>Loading...</mi-nombre-proyecto-app>
EseeselcomponenteraízdenuestraaplicaciónAngular2.Hablaremosdecomponentescondetallemás
adelante.Demomentoparaloqueteinteresaati,queesreconocerelflujodeejecuciónbásico,hayque
decirquesucódigoestáenlacarpeta"src/app".
Enesacarpetaencontrarásvariosarchivosdelcomponentequeanalizaremosconcalmamásadelante.De
momentoverásunarchivo".html"quecontienelavistadeestecomponenteyunarchivo".css"que
contieneelCSS.Situcomponentesellamaba"mi-nombre-proyecto-app",estosarchivossellamarán"mi-
nombre-proyecto.component.html"y"mi-nombre-proyecto.component.css".
Paraterminarestaprimerazambullidaalcódigoterecomendamoseditaresosarchivos.EscódigoHTMLy
CSSplano,porloquenotendrásningúnproblemaencolocarcualquiercosa,siemprequeseaHTMLyCSS
correcto,claroestá.
ParaquienuseAngular1yareconoceráunaestructuracomoesta:
{{title}}
EsunaexpresiónqueAngular2sustituiráporundatoquesedeclaraenelarchivo.tsdelcomponente.De
momentolodejamosahí.
Ejecutarelproyecto
ParacomprobarsituscambiosenelHTMLdelcomponentehantenidoefectopuedesprobarelproyecto.
LaejecucióndeestaaplicaciónyalavimosenelartículodeAngularCLI,porloquenonecesitarásmayores
explicaciones.Detodosmodos,comoresumen,siguelospasos:
Desdelaraízdelproyecto,conelterminal,ejecutamoselcomando:
ng serve
LuegonosdirigimosalaURLquenosindicancomoresultadodelaejecucióndelcomando,queseráalgo
como:
http://localhost:4200/
Entoncesdeberíasverlapáginafuncionandoentunavegador,conelHTMLeditadotalcomolohasdejado
enelarchivo.htmldelcomponenteprincipal.
Enfuturosartículosprofundizaremossobremuchosdelospuntosrelatadosaquí.Demomentocreemos
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 30 de 113
queestaintroducciónalcódigodebeaclarartemuchascosas,oplanteartemuchasotrasdudas.
Siestucaso,notepreocupesporsentirtedespistadoportantosarchivosytantascosasnuevas,puespocoa
pocoiremosfamiliarizándonosperfectamentecontodaestainfraestructura.Paratutranquilidad,decirque
estaeslapartemáscomplejayque,apartirdeaquí,lascosasseránmásagradecidas.Siademásvienesde
Angular1,empezarásareconocermejorlaspiezasqueantesexistíanenelframework.
EsteartículoesobradeAlbertoBasalo
Fuepublicadoporprimeravezen29/06/2016
Disponibleonlineenhttp://desarrolloweb.com/articulos/codigo-proyecto-inicial-angular2.html
IntroducciónaloscomponentesenAngular
UnprimeracercamientoalmundodeloscomponentesenAngular(2enadelante),atravésdel
componenteinicialquesecreaentodonuevoproyecto.Aprenderásareconocersuspartesy
realizaremosunasmodificaciones.
EnAngularsedesarrollaenbaseacomponentes.DesdelaaplicaciónmásbásicadeAngular(2,4oen
adelante),elHolaMundo,todotienequecomenzarporuncomponente.Nuestraaplicación
"componetizada"seconstruirá,laverdad,enbaseaunárboldecomponentesde"n"niveles,desdeun
componenteprincipalasushijos,nietos,etc.
Porsinolosabes,loscomponentessoncomoetiquetasHTMLnuevas,quepodemosinventarnospara
realizarlasfuncionesqueseannecesariasparanuestronegocio.Puedensercosasdiversas,desdeuna
seccióndenavegaciónaunformulario,ouncampodeformulario.Paradefinirelcontenidodeestanueva
etiqueta,elcomponente,usasunpocodeHTMLconsuCSSyporsupuesto,unpocodeJavascriptpara
definirsufuncionalidad.
Básicamenteesoesuncomponente,unadelaspiezasfundamentalesdelasaplicacionesenAngular,que
nostraediversosbeneficiosquemejoransensiblementelaorganizacióndeunaaplicación,su
mantenimiento,reutilizacióndelcódigo,etc.
Paracomenzaraintroducirnoseneldesarrolloenbaseacomponentesvamosarealizarenesteprimer
artículounanálisisdelcomponenteinicial,quecontienedetodaaplicaciónAngularyquepodemos
encontrarenelproyectobásicocreadovíaAngularCLI.
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 31 de 113
Localizarelcomponenteinicial
EnelManualdeAngular2hemosvistoquenuestraaplicaciónsedesarrollaeneldirectorio"src".Allí
encontramoselarchivoindex.htmlraízdelaaplicación..Siloabresverásquenotieneningúncontenidoen
sí.Apenasencontraráselusodeuncomponente,unaetiquetaquenopertenecealHTML.Esfácil
localizarloporqueeselúnicocontenidodelBODYdelapágina.
<app-root></app-root>
Nota:DependiendodetuversióndeAngularestecomponentepuedetenerunnombrediferente.
Además,tambiénpuedecambiarsunombredependiendodelaconfiguracióndelAngularCLI,que
escribesenelarchivo".angular-cli.json".Enprincipiotodosloscomponentessecreanconelprefijo
"app",porloquesiempreempiezanconesasletrasyunguión,como"app-root".Peropodríascambiar
elprefijoeditandoelficherodeconfiguraciónenlapropiedad"prefix"ycolocandocualquierotrovalor.
Ejemplo"prefix":"dw".
EsteeselcomponentedondetuaplicaciónAngular2vaadesarrollarse.Todoslosdemáscomponentes
estarándebajodeéste,unosdentrodeotrosenunárbol.Todoloqueocurraentuaplicación,estarádentro
deestecomponente.
Nota:EnversionestempranasdeAngular2habíauntextocomocontenidodentrodelcomponente
(Loading...)esloqueapareceráenelnavegadormientrasnocargalapágina.Unavezquelaaplicaciónse
inicie,Angularlosustituiráporelcontenidodefinidoparaelpropiocomponente,cuandoarranquela
aplicación.
Sialarrancarlaaplicación(ng-serve)vesqueesemensajede"Loading..."tardaenirseesporqueestás
enmododedesarrolloyantesdeiniciarselaapptienenquehacersevariastareasextra,comotranspilado
decódigo,quenosenecesitaránhacercuandoestéenproducción.
Entendiendoelcódigodelcomponente
Elcódigodeestecomponenteestágeneradodeantemanoenlacarpeta"src/app".Allíencontrarásvarios
ficherosqueformanelcomponentecompleto,separadosporeltipodecódigoquecolocarásenellos.
app.component.html:Equivalealoqueconocemospor"vista"enlaarquitecturaMVC.
app.component.css:Permitecolocarestilosalcontenido,siendoqueéstosestánencapsuladosen
estecomponenteynosalenafuera.
app.component.ts:Eselcorazóndenuestrocomponente,unarchivoconcódigoTypeScript,que
setraduciráaJavascriptantesdeentregarsealnavegador.Porsitesirvelacomparación,seríael
equivalentealcontroladorenelMVC,aunqueenAngular2desaparecióelcontroladortalcomose
conocíaenAngularJS(1.x).
app.component.spec.ts:UnarchivoTypeScriptdestinadoatareasdetestingdecomponentes.
Vistadelcomponente:app.component.html
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 32 de 113
Enestearchivoencontrarásdiversocontenido,expresadoencódigoHTML.Comohemosdicho,este
archivoesloqueseríalavistayadmitetodaclasedecódigoHTML,conetiquetasestándaryelusodeotros
componentes.Ademáspodemoscolocarexpresiones,declararbindigentrecomponentes,eventos,etc.
Nota:Losquenoconozcandetodoesoqueestamoshablando(expresiones,eventos,binding,etc.)no
sepreocupen,porqueloveremosmásadelante.
DentrodelHTMLdelavista,entreotrascosas,encontrarás:
{{title}}
Esoesunaexpresión.Angularlosustiruiráporelcontenidodeunavariable"title"antesdemostrarloal
cliente.Esavariablesedefineenladeclaracióndelcomponente.
Declaracióndelcomponente:app.component.ts
Esteeselarchivoconelscriptnecesarioparalacreacióndelcomponente,creadomediantecódigo
TypeScript.EscomoelcontroladorenelpatrónMVC,soloqueenAngular2noselellamacontrolador,o
"controller".Ahoraesunaclasenormal,deprogramaciónorientadaaobjetos,comolasquenosofreceES6,
sóloqueaquíesTypeScriptquiennoslafacilita.
Siabreselarchivoapp.component.tsencontrarásvariascosas.
Elimportde"component"dentrode@angular/core
Unafuncióndecoradoraquehacelaacciónderegistrarelcomponente
Laclasequehacelasvecesdecontrolador
Lafuncióndecoradoraobservarásquedeclaradiversascuestiones.
@Component({
moduleId: module.id,
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
Unadeellasesel"selector"deestecomponente,oelnombredelaetiquetaqueseusarácuandosedesee
representar.Mediantelapropiedad"templateUrl"asociamosunarchivo.htmlqueseusarácomovistadel
componente.Porúltimosedefinesuestilomediantelapropiedad"styleUrls",indicandoaunarraydetodas
lashojasdeestiloquedeseemos.
Enlaclasedelcomponente,quesedebecolocarconunexportparaqueseconozcafueradeestemódulo,
eslapartequerepresentaelcontroladorenunaarquitecturaMVC.Enellacolocaremostodaslas
propiedadesymétodosquesedeseenusardesdelavista.
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 33 de 113
export class AppComponent {
title = 'proyecto-angular2 works!';
}
Esaspropiedadesrepresentanelmodelodedatosysepodránusarexpresionesenlasvistasparapoder
visualizarlas.
Nota:Observaademásqueelnombredelaclasedeestecomponentetieneunaformaespecial.
Mientrasqueelnombredelaetiquetadelcomponente(su"selector")tienelaspalabrasseparadaspor
guiones,aquítenemosunanotación"PascalCase"típicadelasclases(classdeprogramaciónorientadaa
objetos).Estoesunaconstante:EnelHTMLquenosereconocenmayúsculasyminúsculasseseparan
laspalabrasporguionesporguiones,colocandotodoenminúscula.Porsuparte,losmismosnombres
enJavascriptseescribencon"PascalCase",todojuntoyconlaprimeraletradecadapalabraen
mayúscula.
Alterandoelcódigodenuestrocomponente
Paraterminaresteartículovamosahacerunospequeñoscambiosenelcódigodelcomponentepara
comprobarsilamagiadeAngularestáfuncionando.
Algomuysencilloseríacomenzarporcrearunanuevapropiedadenlaclasedelcomponente.Perovamos
ademásacolocarunmétodoparapoderusarlotambiéndesdelavista.
export class ProyectoAngular2AppComponent {
title = 'Manual de Angular de DesarrolloWeb.com';
visible = false;
decirAdios() {
this.visible = true;
}
}
Nota:Estaclase"class"seescribeenunarchivoTypeScript,perorealmenteloquevemosescasitodo
JavascriptválidoenES6yES7.TypeScriptentiendetodoES6einclusoalgunascosasdeES7.
AhoravamosaverelcódigoHTMLquepodríatenernuestravista.
<h1>
{{title}}
</h1>
<p [hidden]="!visible">
Adiós
</p>
<button (click)="decirAdios()">Decir adiós</button>
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 34 de 113
EnesteHTMLhemosincluidomáscosasdelasquepuedesusardesdeAngular.Habíamosmencionadola
expresión,entrellavesdobles,quepermitevolcarelcontenidodepropiedadesdelcomponente.También
encuentraselusodeunapropiedaddeunelemento,comoes"hidden",entrecorchetes(nuevoenAngular
2).Ademásdeladeclaracióndeunevento"click"quesecolocaentreparénteis.
Nota:Enelsiguienteartículoexplicaremoscondetalletodaestasintaxisnuevaquepodemosusarenlas
vistasparadeclarareventos,hacerdata-binding,etc.
Otrodetallequepuedesobservareslapropiedad"visible"delcomponente,queseusaparaasignarlaal
atributohiddendelelemento"p".Elmétododelaclase,decirAdios()seusaparaasociarlocomomanejador
delevento"click".
Hablaremosmásadelantedetodasestascosasquepuedescolocarenlasvistasyalgunasotras,juntoconlas
explicacionessobrelasintaxisquesedebeusarparadeclararlas.
Nota:Almodificarlosarchivosdelcomponente,cualquieradeellos,tantoelhtml,cssots,sedebería
refrescarautomáticamentelapáginadondeestásvisualizandotuproyectounavezpuestoenmarchacon
elcomando"ngserve",graciasalsistemade"live-reload"quetemontaAngularCLIencualquier
proyetoAngular2.
Otracosainteresantedelentornodetrabajoesque,siusasVisualStudioCodeuotroeditorconlos
correspondientespluginTypeScript,teinformarándeposibleserroresenlosarchivos.js.Esunaayudamuy
útilqueaparecesegúnestásescribiendo.
Conestoacabamosnuestroprimeranálisisymodificacionesenelcomponenteinicial.Estamossegurosque
estaúltimaparte,enlaquehemosmodificadoelcódigodelcomponentebásico,habráresultadoyaalgomás
entretenida.
EsteartículoesobradeAlbertoBasalo
Fuepublicadoporprimeravezen06/07/2016
Disponibleonlineenhttp://desarrolloweb.com/articulos/introduccion-componentes-angular2.html
SintaxisparalasvistasenAngular
Expresiones,binding,propiedades,eventos.Sonmuchascosaslasquepodemosexpresarenlas
vistasHTMLdelasaplicacionesAngular2.Teofrecemosunaintroduccióngeneral.
EnlosartículosanterioresdelManualdeAngularhemosanalizadolaestructuradeunaaplicaciónbásica.
Unadelascosasfundamentalesqueencontramoseselcomponenteprincipal,sobreelcualhemoshecho
pequeñasmodificacionesparacomprobarquelascosasestánfuncionandoycomenzaraapreciarelpoder
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 35 de 113
delframework.
DentrodelcomponentebásicoencontramosvariosarchivosyunodeelloseselcódigoHTMLdel
componente,alquecomúnmentenosreferiremosconelnombrede"vista",denominaciónquevieneporel
patróndearquitecturaMVC.Puesbien,enesecódigoHTML-lavista-,demaneradeclarativa,podemos
definiryusarmuchasdelaspiezasconlasquecontamosenunaaplicación:propiedades,eventos,bindeo…
LanovedadenAngular(2,4yenadelante),paralosquevienendelaversiónanteriordelframework,esque
ahorapodemossermuchomásprecisossobrecómoqueremosquelainformaciónfluyaentre
componentes,entrelavistayelmodelo,etc.Enesteartículovamosaofrecerunaprimeraaproximación
generalatodoloquesepuededeclarardentrodeunavista,teniendoencuentaquemuchasdelascosas
necesitaránartículosespecíficosparaabordarlasenprofundidad.
Nota:Enesteartículo,asícomoalolargodelmanual,hacemosusoconstantementedeconceptosdel
MVC.RecordamosqueexisteunartículogenéricodeloqueeselMVC,introducciónalmodelovista
controlador.Detodosmodos,enAngular2noseaplicaunaimplementaciónperfectamenteclarasobre
elMVC.Existeunaseparacióndelcódigoporresponsabilidades,loqueyanosaportalosbeneficiosde
laarquitecturaporcapas,perolaimplementaciónycaracterísticasdeestascapasnoquedatandefinida
comopodríadarseenunframeworkbackend.Enesteartículoylossiguientesverásquehacemos
referenciaalosmodelosyrealmentenoesqueexistaunaclaseoalgoconcretodondesecolocael
códigodelmodelo.Esemodelorealmentesegeneradesdeelcontroladoryparaelloelcontrolador
puedeobtenerdatosdediversasfuentes,comoserviciosweb.Esosdatos,tantopropiedadescomo
métodos,sepodránusardesdelavista.EsalgomásparecidoaunVW(ViewModel),osea,unmodelo
paralavista,quesecreaenelcontrolador.Porotraparte,tampocoexisteuncontrolador,sinounaclase
queimplementaelViewModeldecadacomponente.Enresumen,conocerelMVCteayudaráa
entenderlaarquitecturapropuestaporAngular2yapreciarsusbeneficios,perodebemosmantenerla
menteabiertaparanoconfundirnosconconocimientosqueyapodamostenerdeotrosframeworks.
HTMLpermitidoenlosTemplatesdeAngular
Lostemplatesdeloscomponentes.ovistasdeloscomponentes,yaseancolocadosinlineenelpróximo
códigoTypeScriptoenunarchivoaparte,seescribenconHTMLypermitencolocarmediantelasintaxisde
Angularexpresiones,bindeos,eventos,etc.quevamosaintroducirenesteartículo.
CasitodoelHTMLválidoesuncódigopotencialmenteusableenlostemplatesdeAngular.Sinembargo
hayalgunasexcepcionesqueconvieneconocer.
NoestápermitidocolocarscriptsJavascripteneltemplate
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 36 de 113
LamásimportanteexcepcióndeHTMLválidoausarenuntemplate(unavista)eslaetiquetaSCRIPT,ya
quepuedeserorigendeproblemasdeseguridad.Bajoelprismadelaseparacióndelcódigopor
responsabilidades,nodeberíamoscolocarunaetiquetaSCRIPTdentrodeuntemplate,pueslapartedel
desarrollodelalógicadeloscomponentessedeberíacolocarenelcódigoTypeScript.
Pero,aúncometiendolaimprudenciaomalaprácticadecolocarunaetiquetaSCRIPT,Angularharácaso
omisodeellaynoejecutaráesecódigoJavascript,evitandoposiblesproblemaseinyeccionesdecódigono
deseado.
Nota:estomismoocurresienunacadenavolcadaenuntemplateporinterpolación{{}}obindeoa
propiedad[[]]contieneunaetiquetaSCRIPT.Angularsedaráeltrabajodesanitizarelcódigoacolocar
eneltemplate,evitandoproblemascomolainyeccióndecódigo(xss).
Mástardeenesteartículoexplicamoslainterpolación(sintaxis{{}}doblesllaves)yelbindeoa
propiedades(sintaxis[[]]doblescorchetes),quesondosdelasprincipalespiezasdeclarablesenuna
vista.Aunqueenocasioneslainterpolaciónlanombraremoscomo"expresiones"yelbindingaa
propiedadlonombramossimplementecomo"propiedad".Nosreferimosalomismo,esperamosno
liarte.
Notienesentidousarciertasetiquetas
Hayotrasetiquetasquetampocotienesentidousarseenuntemplate,comoBODYoHEAD.Un
componenteesunaparteconcretadelapágina,nolacabecera,nielcuerpo,porloquenotendríanninguna
utilidadcolocaresasetiquetasenuntemplate.
OtraetiquetanousableesBASE,quesirveparaindicarporejemplolarutadebasealaqueaplicartodaslas
rutasrelativasdelosenlacesentodoeldocumentoHTML.
Porlodemás,puedesusarprácticamentecualquierotroHTMLdisponibleenellenguajedemarcación.
Piezasdeclarablesenunavista
Comenzaremospordescribirlascosasquedisponemosparasudeclaraciónenunavista,demodoque
todospodamosusarunúnicovocabulario.
Propiedad:CualquiervalorquepodemosasignarpormediodeunatributodelHTML.Ese
elementopuedesersimplementeunatributodelHTMLestándar,unatributoimplementado
medianteelpropioAngular2ounatributopersonalizado,creadoparauncomponenteen
específico.
Expresión:Esunvolcadodecualquierinformacióneneltextodelapágina,comocontenidoa
cualquieretiqueta.LaexpresiónesunadeclaraciónqueAngularprocesaráysustituiráporsuvalor,
pudiendorealizarsencillasoperaciones.
Binding:Esunenlaceentreelmodeloylavista.Medianteunbindingsiundatocambiaenel
modelo,esecambioserepresentaenlavista.PeroademásenAngularseintroduceel"doble
binding",porelcualsiunvalorsemodificaenlavista,tambiénviajahaciaelmodelo.Conla
novedadenAngular(2enadelante)queeldoblebindingesopcional.
Evento:esunsucesoqueocurreyparaelcualsepuedendefinirmanejadores,quesonfunciones
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 37 de 113
queseejecutaráncomorespuestaaesesuceso.
Nota:Generalmentecuandohablemosde"binding"enlamayoríadelasocasionesnosreferimosa
"doblebinding",queeslaprincipalnovedadquetrajoAngular1yqueleprodujotantoéxitoparaeste
framework.Sinembargo,estemismodoblebindingesunarmadedoblefilo,puespuededisminuirel
rendimientodelaaplicaciónyenocasionespuedeproducirunflujodedatosdifícildeentendery
depurar.
Debidoalcosteoperacionaldeldoblebinding(costeentiempodeprocesamientosilaaplicaciónesmuy
complejayseproducenmuchosenlaces),lavelocidaddeAngularpuedeverseafectada.Eselmotivoporel
quesehanproducidonuevassintaxisparapoderexpresarbindingsdevariostipos,deunaydedos
direcciones.Dichodeotramanera,ahoraseentregaalprogramadorelcontroldelflujodelainformación,
paraqueéstepuedaoptimizarelrendimientodelaaplicación.
Flujodelainformacióndelavistaalmodeloymodeloavista
Elprogramadorahoraserácapazdeexpresarcuándounainformacióndebeirdelmodelohacialavistay
cuándodebeirdesdelavistaalmodelo.Paraellousamoslasanteriores"piezas"o"herramientas"enel
HTML,lascualestienendefinidadeantemanounsentidoparaelflujodelosdatos.
EnelsiguientediagramapuedesverunresumendelflujodelainformacióndisponibleenAngular,junto
conlaspiezasdondepodemosencontrarloysusintaxis.
1. Laspropiedadestienenunflujodesdeelmodeloalavista.Unainformacióndisponibleenel
modelosepuedeasignarcomovalorenunelementodelHTMLmedianteunapropiedad,usandola
notacióncorchetes.Porej:[propiedad]
2. Lasexpresionestambiénviajandesdeelmodeloalavista.Ladiferenciadelaspropiedadesesqueen
estecasolasusamoscomocontenidodeunelementoyademásqueseexpresancondoblesllaves.
Porej:{{expresión}}
3. Elbinding(adossentidos,odoblebinding)loexpresamosentrecorchetesyparéntesis.Eneste
casolainformaciónfluyeenambossentidos,desdeelmodeloalavistaydesdelavistaalmodelo.
Porej:[(ngBind)]
4. Loseventosnoesquenecesariamentehaganfluirundato,perosíseconsideraunflujode
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 38 de 113
aplicación,enestecasodelavistaalmodelo,yaqueseoriginanenlavistaygeneralmentesirven
paraejecutarmétodosqueacabaránmodificandocosasdelmodelo.Porej:(evento)
Nota:Comoves,ahoraexistendiversassintaxisparaexpresarcosasenlasvistas.Quizásnosresulte
extraño,peroenseguidanosfamiliarizaremos.Lanotaciónmásraraeslaqueusamosparaexpresarun
bindingendosdirecciones[(ngBing)],perounamanerasencilladeacordarnosdeellaesconsu
denominaciónanglosajona"bananainabox".Losparéntesisparecenunabanana,dentrodelos
corchetes,queparecenunacaja.
EjemplosdesintaxisutilizadaenvistasdeAngular2
Realmenteyahemosvistoejemplosdebuenapartedelaspiezasposiblesadeclararenunavista.Sitefijas
enelartículoanteriordedicadoalaIntroducciónaloscomponentesenAngular2.Ahoralespodemosdar
nombresacadaunodeloselementosencontrados.
Propiedades:
Eraelcasodelapropiedad"hidden"queusamosparamostrar/ocultardeterminadoselementos.Eneste
caso,hiddennoesunapropiedadestándardelHTML,sinoqueestágeneradaporAngular2ydisponible
paraaplicartantoenetiquetasHTMLcomunescomoencomponentespersonalizados.
<p [hidden]="!visible">Adiós</p>
TambiénpodríamosaplicarvaloresaatributosdelHTMLcondatosqueestánenpropiedadesdelmodelo,
aunquenosoportatodoslosatributosdelHTMLestándar.Porejemplo,podríamosasignarunaclaseCSS
(class)conloquetuviésemosenunapropiedaddelmodelollamada"clase".
<div [class]="clase">Una clase marcada por el modelo</div>
Oelenlacedeunenlacepodríamostambiéndefinirlodesdeunavariabledelmodeloconalgocomoesto:
<a [href]="enlace">Pulsa aquí</a>
Enelcódigoanteriorsesuponequeelcomponentetendráunapropiedadllamada"enlace",queservirápara
volcarsucontenidoenelhrefdelaetiquetaA.
Engeneral,elusomáscorrientequeharemosdelaspropiedadesespersonalizarelestadoo
comportamientodelcomponente,mediantedatosquetengamosenelmodelo.Veremosestecasomás
adelantecuandoanalicemosconmayordetalleloscomponentes.
Loquedemomentodebequedarclaroesquelaspropiedadesvandesdeelmodeloalavistay,portanto,si
semodificaelvalordeunapropiedadenelmodelo,tambiénsemodificarálavista.Pero,sidentrodela
vistasemodificaunapropiedadnoviajaráalmodeloautomáticamente,pueselenlaceesdeunasola
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 39 de 113
dirección.
ObtendrásmásdetallessobreelbindeoapropiedadenelartículodedicadoaPropertybindingdeAngular.
Expresiones:
Eselcasodelapropiedaddelmodelo"title"quesevuelcacomocontenidodelapáginaenel
encabezamiento.
<h1>
{{title}}
</h1>
Simplementeexisteesasustitucióndelvalordelapropiedad,colocándoseeneltextodelapágina.Elenlace
esdeunaúnicadirección,desdeelmodeloalavista.Enlavistatampocohabríaposibilidaddemodificar
nada,porqueesunsimpletexto.
ElcasodepropiedadesdelHTMLconvaloresquevienendelmodelotambiénpodríamosimplementarlo
pormediodeexpresiones,talcomosigue.
<a href="{{enlace}}">Clic aquí</a>
Nota:Lasdosalternativas(usarexpresionesconlasllavesoloscorchetesparapropiedades,como
hemosvistoparaelejemplodeunhrefdeunenlacecuyovalortraesdelmodelo)funcionan
exactamenteigual,noobstanteparaalgunoscasosserámejorusarlasintaxisdepropiedadesenvezdela
deexpresiones,comoeselcasodelenlace.Algoqueentenderemosmejorcuandolleguemosalsistema
derutas.
ExplicamosmássobrelasexpresionesenelartículosobreStringinterpolationdeAngular.
Eventos:
Estotambiénlovimosenelartículoanterior(introducciónacomponentes),cuandoasociamosun
comportamientoalbotón.Indicamosentreparéntesiseltipodeeventoycomovalorelcódigoquesedebe
deejecutar,omejor,lafunciónquesevaaejecutarparaprocesarelevento.
<button (click)="decirAdios()">Decir adiós</button>
ConrespectoaAngular1.xentenderásqueahoratodaslasdirectivascomong-clickdesaparecen,dadoque
ahoraloseventossololostienesquedeclararconlosparéntesis.Estoesinteresanteyadeentrada,porque
nospermitedefinirdeunaúnicamaneracualquiereventoestándardelnavegador,peroesmásinteresante
todavíacuandocomencemosausarcomponentespersonalizados,creadospornosotros,quepodrán
disparartambiéneventospersonalizados.Capturaresoseventospersonalizadosserátanfácilcomocapturar
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 40 de 113
loseventosestándardelHTML.
Doblebinding:
Paraesteúltimocasonohemosvistotodavíaunaimplementacióndeejemplo,perolovamosaconseguir
muyfácilmente.Comosedijo,usamoslanotación"bananainabox"paraproducirestecomportamientode
bindingendosdirecciones.Losdatosviajandelavistaalmodeloydelmodeloalavista.
<p>
¿Cómo te llamas? <input type="text" [(ngModel)]="quien">
</p>
Enestecaso,desdeelHTMLestaríamoscreandounapropiedaddentrodelmodelo.Esdecir,aunqueno
declaremoslapropiedad"quien"enelJavascript,porelsimplehechodeusarlaenlaestructuradebinding
vaaproducirquesedeclareautomáticamenteyseinicialiceconloquehayaescritoenelcampodetexto.Si
ladeclaramos,olainicializamosdesdelaclasequehacelasvecesdecontrolador,tantomejor,peronoserá
necesario.
ACTUALIZADO:TenmuyencuentaqueparapoderusarngModelnecesitasimportarunmódulo
adicional,disponiblemedianteelpropioAngular,peroquenovienecargadopordefecto.Estoocurre
desdeAngular4.Ahora,cuandoquierasusarladirectivangModeltendrásquehacerelimportde
FormsModule.Enestemomentodelmanualesunpocoprontoparaexplicartodoslosdetallesdeesta
importación.Lotendrástodomásclaromásadelante,cuandohablemosespecíficamentedelosmódulosy
sobretodoenelartículoenelqueexplicamostodaslasposibilidadesdeladirectivangModel.
Nota:Lanotación"bananainabox"tieneunaexplicaciónyesqueusatantoelflujodedatosdesdeel
modeloalavista,queconseguimosconloscorchetesparalaspropiedades,comoelflujodesdelavista
almodeloqueconseguimosconlosparéntesisparaloseventos.
ParaquienconozcaAngular1.x,ngModelfuncionaexactamenteigualquelaantiguadirectiva.Enresumen,
leasignamoselnombredeunapropiedadenelmodelo,enestecaso"quien",conlaquesevaaconocerese
dato.Apartirdeentoncesloquehayaescritoenelcampodetextoviajarádelavistaalmodeloysicambia
enelmodelotambiénseactualizarálavista,produciendoelbindingenlasdosdirecciones.
Siquisiéramosvisualizaresedatoenalgúnotrodelavista,porejemploenunpárrafo,usaríamosuna
expresión.Porejemplo:
<p>
Hola {{quien}}
</p>
Conclusión
ConloquehemosaprendidohastaaquítenemosunabaseinicialconlaquecomenzarausarAngulary
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 41 de 113
realizarpequeñosejemplossinperdernosdemasiado.Podemosdecirquehemosdadonuestroprimerpaso
enelaprendizaje.TerecomendamospararuninstantelalecturadelManualdeAngularparaexperimentar
unpocoportucuenta,cambiandoelcódigoenlavistayenelcomponenteraízdelaaplicación,para
afianzaresteconocimiento
Enlospróximosartículosdelmanualvamosaabordarconmayordetalleelmodelodecomponentes,
construyendonuevoscomponentesennuestroproyectoypracticandocontodolovistohastaahora.
Nuestrosiguientepasoesexplicarconmayordetallecómoeslaarquitecturadecomponentes,yaqueesun
conceptoimportanteeneldesarrolloconAngular.
EsteartículoesobradeMiguelAngelAlvarez
Fuepublicadoporprimeravezen19/07/2016
Disponibleonlineenhttp://desarrolloweb.com/articulos/sintaxis-vistas-angular2.html
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 42 de 113
LoscomponentesenAngular
Abordamoseldesarrollobasadoencomponentescontododetalle.EslapiezamásimportantedeAngular
quenospermitiránosoloestructurarunaaplicacióndeunamaneraordenada,sinoencapsularfuncionalidad
yfacilitarunaarquitecturaavanzadaydefácilmantenimientodelosproyectosJavascriptconlanueva
versióndeesteframework.
ElconceptodeloscomponentesenAngularysuarquitectura
QuéesuncomponenteparaAngularycómousaremosloscomponentespararealizarla
arquitecturadeunaaplicación.
EnesteartículodelManualdeAngular2queremosabordarelconceptodelcomponentedesdeunpuntode
vistateórico,sinentraravercómoseconstruyenenAngular2.Esaparteprácticaladejaremosparael
próximoartículo,aunquecaberecordar,paralosqueseimpacientanporvercódigo,queyadimosuna
zambullidaenelcódigodeloscomponentescuandocomenzamosconel"holamundo".
ElobjetivoesentendermejorcuáleslaarquitecturapromovidaporAngular2paraeldesarrollode
aplicacionesyquépapelespecíficodesempeñanloscomponentes.Esimportanteporquetodaaplicación
Angular2sedesarrollaenbaseacomponentesyporqueesalgorelativamentenuevoenelframework.
Árboldecomponentes
UnaaplicaciónAngular2sedesarrollaabasedecrearcomponentes.Generalmentetendrásunárbolde
componentesqueformantuaplicaciónycadapersonalopodráorganizardesumanerapreferida.Siempre
existiráuncomponentepadreyapartirdeahípodráncolgartodaslasramasqueseannecesariasparacrear
tuaplicación.
Estonoresultaránadaextraño,puessipensamosenunapáginawebtenemosunmismoárboldeetiquetas,
siendoBODYlaraízdelapartedelcontenido.Ladiferenciaesquelasetiquetasgeneralmentesonpara
mostraruncontenido,mientrasqueloscomponentesnosoloencapsulanuncontenido,sinotambiénuna
funcionalidad.
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 43 de 113
Ennuestroárbol,comoposibleorganización,podemostenerenunprimernivellosbloquesprincipalesde
lapantalladenuestraaplicación.
Unabarradeherramientas,coninterfacesparaaccionesprincipales(loquepodríaserunabarrade
navegación,menús,botonera,etc.).
Unaparteprincipal,dondesedesplegaránlasdiferentes"pantallas"delaaplicación.
Unáreadelogueodeusuarios.
Etc.
Nota:Obviamente,eseprimerniveldecomponentesprincipaleslodictaráelpropioproyectoypodrá
cambiar,peroloanteriornossirveparahacernosunaidea.
Luego,cadaunodeloscomponentesprincipalessepodrásubdividir,sisedesea,ennuevosárbolesde
componentes.
Enlabarradeherramientasprincipalpodríamosteneruncomponenteporcadaherramienta.
Eneláreaprincipalpodríamosteneruncomponenteparacada"pantalla"delaaplicacióno"vista".
Asuvez,dentrodecada"vista"o"pantalla"podíamostenerotraseriedecomponentesque
implementendiversasfuncionalidades.
Etc.
Losnivelesdelárbolseránlosquecadaaplicaciónmande,atendiendoasucomplejidad,ycadadesarrollador
estimenecesario,enfuncióndesuexperienciaopreferenciasdetrabajo.Amedidaquecomponetizamos
conseguimosdividirelcódigodelaaplicaciónenpiezasmenores,conmenorcomplejidad,loque
seguramenteseabeneficioso.
Sillegamosaunextremo,ynospasamosennuestraansiadecomponetizar,quizásobtengamoselefecto
contrario.Esdecir,acabemosagregandocomplejidadinnecesariaalaaplicación,puestoqueexisteuncoste
detiempodetrabajoyrecursosdeprocesamientoparaposibilitarelflujodecomunicaciónentre
componentes.
ComponentesVsdirectivas
EnAngular2perduraelconceptodedirectiva.Peroahoratenemoscomponentesylarealidadesque
ambosartefactossepodríanaprovecharparausossimilares.Laclaveenestecasoesqueloscomponentes
sonpiezasdenegocio,mientrasquelasdirectivassesuelenusarparapresentaciónyproblemas
estructurales.
Puedespensarenuncomponentecomouncontenedordondesolucionasunanecesidaddetuaplicación.
Unainterfazparainteracción,unlistadodedatos,unformulario,etc.
Paraserexactos,enladocumentacióndeAngular2nosindicanqueuncomponenteesuntipodedirectiva.
Existientrestiposdedirectivas:
Componentes:Uncomponenteesunadirectivaconuntemplate.Habrámuchasentuaplicacióny
resuelvennecesidadesdelnegocio.Directivasdeatributos:Cambianlaaparienciaocomportamientode
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 44 de 113
unelement.PorejemplotenemosngClass,quenospermitecolocarunaomásclasesdeCSS(atributoclass)
enunelemento.Directivasestructurales:SonlasquerealizancambiosenelDOMdeldocumento,
añadiendo,manipulandooquitandoelementos.PorejemplongFor,quenossirveparahacerunarepetición
(similaralngRepeatdeAngular1.x),ongIfqueañadeoremueveelementosdelDOMconrespectoauna
expresióncondicional.
Portanto,adiferenciadeotraslibreríascomoPolymer,dondetodoseresuelvemediantecomponentes,hay
quetenerencuentaquécasosdeusosonlosadecuadospararesolverconuncomponente.
Laspartesdeuncomponente
Aunquetambiénhemosanalizadoanteriormente,cuandorepasamoslaaplicaciónbásicadeAngular2
generadaconAngularCLI,cuálessonlaspartesfundamentalesdeuncomponente,vamosavolveraeste
puntoparapoderversuspiezasdemaneraglobal.
Uncomponenteestácompuestoportrespartesfundamentales:
Untemplate
Unaclase
Unafuncióndecoradora
LasdosprimeraspartescorrespondenconcapasdeloqueconocemoscomoMVC.Eltemplateseráloque
seconocecomovistayseescribeenHTMLyloquecorresponderíaconelcontroladorseescribeen
Javascriptpormediodeunaclase(deprogramaciónorientadaaobjetos).
Porsuparte,tenemoseldecorador,queesunaespeciederegistrodelcomponenteyquehacede
"pegamento"entreelJavascriptyelHTML.
Todasestaspartessonlasquevamosaanalizarenlospróximosartículosconmayordetalle,comenzando
porlosdecoradores,queintroduciremosenelpróximoartículo.
EsteartículoesobradeAlbertoBasalo
Fuepublicadoporprimeravezen01/08/2016
Disponibleonlineenhttp://desarrolloweb.com/articulos/concepto-teorico-componente-angular2.html
DecoradordecomponentesenAngular2
Quéesundecoradordecomponentes,quéfuncióntieneycómoseimplementaenuncomponente
básicodeAngular2.
Ahora,unadelasfuncionesbásicasquevasatenerquerealizarentododesarrolloconAngularesla
decoracióndecomponentes.Ensí,noesmásqueunadeclaracióndecómoseráuncomponenteylas
diversaspiezasdelasqueconsiste.
Enelartículodeintroducciónaloscomponentesexplicamossolounadelaspartesquetieneelarchivo.ts
conelcódigoJavascript/TypeScriptprincipaldeuncomponente.Loquevimoshastaahoraeralaclase
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 45 de 113
que,decíamos,hacíalasvecesdecontrolador,queseexportahaciaafueraparaqueelflujoprincipalde
ejecucióndeunaaplicaciónseacapazdeconoceralcomponente.Además,contieneloquesellamauna
funcióndecoradoraqueconoceremosacontinuación.
Quéesundecorador
UndecoradoresunaherramientaquetendremosanuestradisposiciónenJavascriptenunfuturopróximo.
EsunadelaspropuestasparaformarpartedelestándarECMAscript2016,conocidotambiéncomoES7.
Sinembargo,yaestándisponiblesenTypeScript,porloquepodemoscomenzarausarlosyaenAngular.
Básicamenteesunaimplementacióndeunpatróndediseñodesoftwarequeensísirveparaextenderuna
funciónmedianteotrafunción,perosintocaraquellaoriginal,queseestáextendiendo.Eldecoradorrecibe
unafuncióncomoargumento(aquellaquesequieredecorar)ydevuelveesafunciónconalguna
funcionalidadadicional.
Lasfuncionesdecoradorascomienzanporuna"@"yacontinuacióntienenunnombre.Esenombreesel
deaquelloquequeramosdecorar,queyatienequeexistirpreviamente.Podríamosdecorarunafunción,una
propiedaddeunaclase,unaclase,etc.
Miralaprimeralíneadelcódigodelarchivo.tsdetucomponenteprincipal.
import { Component } from '@angular/core';
EseimportnosestátrayendolaclaseComponent.Enlasiguientelíneasedecoraacontinuación,conel
correspondiente"decorator".Noesnuestroobjetivohablarsobreelpatróndecoratorensí,niverlas
posibilidadesdeestaconstrucciónqueseguramentetendremosenelfuturoES7,asíquevamosacentrarnos
enloqueconseguimoshacerconAngular2medianteestosdecoradores.
Nota:UnodelosmotivosporlosqueAngular2hatomadoTypeScriptcomolenguajeesjustamente
porpermitirusardecoradores.ConTypeScriptpodemosrealizarladecoracióndecódigodeES7ya
mismo,loquefacilitaladecoracióndelcódigo.
Quéinformaciónseagregapormediodeldecorador
Angular2usalosdecoradorespararegistraruncomponente,añadiendoinformaciónparaqueéstesea
reconocidoporotraspartesdelaaplicación.Laformadeundecoradoreslasiguiente:
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 46 de 113
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
Comoapreciarás,eneldecoradorestamosagregandodiversaspropiedadesespecíficasdelcomponente.Esa
informaciónenestecasoconcretoseconocecomo"anotación"yloqueleentregamossonunos
"metadatos"(metadata)quenohacemásquedescribiralcomponentequeseestácreando.Enestecasoson
lossiguentes:
selector:esteeselnombredelaetiquetanuevaquecrearemoscuandoseproceseelcomponente.Es
laetiquetaqueusaráscuandoquierascolocarelcomponenteencualquierlugardelHTML.
templateUrl:eselnombredelarchivo.htmlconelcontenidodelcomponente,enotraspalabras,el
quetieneelcódigodelavista.
styleUrls:esunarraycontodaslashojasdeestilosCSSquedebenprocesarsecomoestilolocalpara
estecomponente.Comoves,podríamostenerunaúnicadeclaracióndeestilos,ovariassilo
consideramosnecesario.
Nota:EsecódigodeanotaciónodecoracióndelcomponenteesgeneradoporAngularCLI.Además,
cuandocreemosnuevoscomponentesusaremoselmismoAngularCLIparaobtenerelscaffolding
(esqueleto)delcualpartiremos.Portanto,nohacefaltaquememoriceslasintaxisparaladecoración,
porqueteladaránhecha.Entodocasotendrásquemodificarlasiquierescambiarelcomportamiento
delcomponente,losnombresdearchivosdeltemplate(vista),hojasdeestilo,etc.
Demomentononecesitamosdarmuchamásinformaciónsobrelosdecoradores.Esalgoquedebemos
comenzarausarparadesarrollarcomponentesenAngular2,perononostienequepreocupardemasiado
todavía,porquedemomentononecesitaremostocarmuchosobreellos.
Conestocreemosquehemosdetalladoperfectamenteelcomponenteinicialdenuestraaplicación,el
generadoporAngularCLIalinicializarelproyecto.Enelpróximoartículo,porfin,podremoscrearnuestro
primercomponentepropio.
EsteartículoesobradeMiguelAngelAlvarez
Fuepublicadoporprimeravezen09/08/2016
Disponibleonlineenhttp://desarrolloweb.com/articulos/decorador-componentes-angular2.html
CrearuncomponentenuevoconAngular2
EnesteartículotevamosaenseñaracrearunnuevocomponenteconAngularCLIyluegoa
usarloentuaplicaciónAngular2.
DespuésdenuestrorepasoteóricoalafiguradeloscomponentesenAngularestamosencondicionesde
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 47 de 113
irnosalterrenodeloprácticoyvercómosegenerannuevoscomponentesenunaaplicación.
Siabreselindex.htmlquehayenlacarpeta"src"veráscomoenelbodyexisteunúnicocomponente,pero
sinembargo,unaaplicacióndeAngulartendrádecenasocientosdeellos.Loscomponentessepueden
organizardediversasmanerasyveremosmásadelantecuandolleguemosalosmódulos,quelospodemos
crearenelmóduloprincipaldelaaplicaciónoenmódulosespecíficosdeunafuncionalidadenconcreto.De
momentovamosacrearuncomponenteenelmóduloprincipal,pueseslomássencilloparacomenzar.
Nota:Ademásdemódulos,recuerdaqueunoscomponentesusaránoseapoyaránenotrospara
resolversusnecesidades,creandounaestructuradeárbol.Todosloscomponentesquedesarrollemosen
adelanteestarándealgunamaneradentrodelcomponenteraíz.Estonoesnuevo,puestoqueyase
comentóenelManualdeAngular,peroestábienrecordarloparaquequedeclaro.Partiremosdeesta
situaciónagregandoahoranuevoscomponentesconlosquepodremosexpandirlaaplicación.
Pero,enrealidad,nadieteobligaateneruncomponenteúnicocomoraíz.Podríascrearuncomponente
yusarlodirectamenteenelindex.htmldetuaplicación.Haciendoestoconvenientemente(puestendrías
queagregaresecomponentealbootstrapdelmóduloprincipalparaquefuncione)nohabríaningún
problemaporello.Aunquedebidoaqueeseindex.htmlescódigogeneradoygeneralmentenolo
querremostocar,serámásrecomendablecrearloscomponentesdebajodelcomponenteraíz.
CreamosuncomponenteatravésdeAngularCLI
YausamosAngularCLIparagenerarelcódigodeiniciodenuestraaplicaciónAngular.Ahoravamosausar
estaherramientadelíneadecomandosparagenerarelesqueletodeuncomponente.Desdelaraízdel
proyectolanzamoselsiguientecomando:
ng generate component nombre-del-componente
Nota:Existeunaliasparalaorden"generate"quepuedesusarparaescribirunpocomenos.Sería
simplementeescribir"g".Seríaalgocomong g component nombre-del-componente
Ademásdecomponentes,laordengeneratetepermitecrearelesqueletodeotraseriedeartefactoscomo
sondirectivas,servicios,clases,etc.
Reconociendolosarchivosdelcomponente
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 48 de 113
Siobservasahoralacarpeta"src/app"encontrarásquesehacreadoundirectorionuevoconelmismo
nombredelcomponentequeacabamosdecrear.Dentroencuentrasunaseriedearchivosqueyatedeben
desonarporqueloshemosanalizadoyaparaelcomponenteinicialdelasaplicacionesAngular.
Nosreferimosalosarchivosdondecolocaselcódigo(TypeScript)deregistrodelcomponente,elCSSpara
losestilosyelHTMLparalavista,máselarchivospec.ts,quesirveparaeltesting.Tendrásendefinitiva
algocomopuedesverenlaimagen.
Nota:EnversionestempranasdeAngular(enestaocasiónnosreferimosaAngular2,almenosensus
primerasreleases),existíaunarchivollamado"index.ts",quehacíasolotieneunexportyservíapara
importarelcomponentedemaneraalgomásresumida.Enindex.ts,seexportabaelpropiocomponente,
porsunombre.Servíaparaque,cuandoimportasuncomponentedesdeotrolugardetuaplicación,no
tengasquereferirtealarchivo"nombre-del-componente.component.ts"contodassusletras,sino
simplementealacarpetadondeseencuentra.AhoraenAngular(4)esearchivonoexiste.
Componentedeclaradoenelmóduloprincipal
Comohemosdicho,estecomponentequeacabamosdecrerarresidiráenelmóduloprincipal.Enadelante
cuandoveamosmódulosexplicaremoscómohacerqueelcomponentesecreedentrodeunmódulo,pero
porelmomentoestaeslasituación.Endichomóduloprincipal,archivoapp.module.ts,setieneque
declararelcomponentequeacabamosdecrear.
Realmente,alcrearelcomponentemedianteelterminal,conloscomandosdelAngularCLI,las
modificacionesenelmóduloprincipalenfocadasaladeclaracióndeestenuevocomponenteyaestán
realizadas.Noobstanteesbuenoqueleechemosunvistazoparairnosfamiliarizando.
Siabreselarchivoapp.module.ts,tendríasquereconocerladeclaraciónenestosbloquesdecódigo:
1.-Elimportdelcomponente
EsteimportnostraeelcódigoTypeScriptdelcomponentequeacabasdecrear.Fíjatelaclasedel
componenteylarutadondeestáelcódigoimportado.
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 49 de 113
import { NombreDelComponenteComponent } from './nombre-del-componente/nombre-del-componente.component';
2.-Ladeclaración"declarations"
Eneldecoradordelmóduloprincipal,enelarraydedeclarations,encontrarásnombradoelcomponente
queacabasdecrear.
@NgModule({
declarations: [
AppComponent,
NombreDelComponenteComponent
],
[...]
}
Nota:Anteriormente,versionesmuytempranasdeAngular2,seusabaSystemJSparaladeclaracióndel
componente.EstonoaplicaalasversionesactualesdeAngular:Entodosloslugaresdonde,en
adelante,deseabasusaresecomponente,conSystemJSestabasobligadoaimportarloparaquese
conozcasucódigo.Paraellohemosvistoquesoloseusabaelnombredelcomponenteynoelarchivo
dondeseescribiósuclase.Insistimos,esoeraantes,cuandopararealizartodoloqueeslacargade
módulosseutilizabaSystemJS.Enaquellaépocaexistíaunarchivollamadosystem-config.tsdondese
administrantodaslaslibreríasqueseimportabanconSystemJS.Enellasencontraríasladeclaracióndel
nuevocomponentequeacabamosdegenerar.
Javascriptdenuestrocomponente
Elarchivo"nombre-del-componente.component.ts"contieneelcódigoJavascriptdelcomponente.
Nota:Apreciarásquedeberíamosdecirquecontieneel"códigoTypeScriptdelcomponente",dadoque
enrealidadadíadehoyAngularCLIsolotienelaopcióndegenerarcódigoTypeScript.Nodebe
representarungranproblemaparati,porquerealmentetodocódigoJavascriptestambiéncódigo
TypeScript,alqueseleagreganciertascosas,sobretodoparaelcontroldetipos.
Debesreconoceryadiversaspartes:
Importsdetodoaquelloquenecesitemos.Enprincipiodelalibrería@angular/core,peroluego
veremosqueaquíiremoscolocandomuchosotrosimportsamedidaquevayamosnecesitando
códigodemáslugares.
Decoradordelcomponente,parasuregistro.
Clasequehacelasvecesdelcontrolador,quetengoqueexportar.
Enestaspartesyaconocidasnoentraremosdemomentoconmásdetalles,puesyaloshemosabordado
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 50 de 113
anteriormenteenelManualdeAngular.Ahoratepedimossimplementeecharunvistazoalacabeceradela
clase,enconcretoasu"implements":
export class NombreDelComponenteComponent implements OnInit {
Eseimplementsesunainterfaz,quenoestándisponiblestodavíaenJavascript,nitansiquieraenES6,pero
queyasonposiblesdeusargraciasaTypeScript.Essimplementecomouncontratoquedicequedentrode
laclasedelcomponentevamosadefinirlafuncionngOnInit().Sobreesafunciónnohablaremosmucho
todavía,peroesunlugardondepodremoscolocarcódigoaejecutarcuandosetengalacertezaqueel
componentehasidoinicializadoya.
Soloamododeprueba,vamosacrearunapropiedadllamada"dato"dentrodenuestrocomponenterecién
creado.Elcódigonosquedaráalgocomoesto:
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-nombre-del-componente',
templateUrl: 'nombre-del-componente.component.html',
styleUrls: ['nombre-del-componente.component.css']
})
export class NombreDelComponenteComponent implements OnInit {
dato = "Creando componentes para DesarrolloWeb.com";
constructor() {}
ngOnInit() {
console.log('componente inicializado...');
}
}
HTMLdelcomponente
ElcomponentequeacabamosdecreartieneunHTMLdeprueba,yaescritoenelarchivo"nombre-del-
componente.component.html".
Podemosagregarlelaexpresiónparaqueseveaenelcomponentelapropiedadquehemosgeneradodel
ladodeJavascript,enlaclasedelcomponente.Tendríasalgocomoesto:
<p>
nombre-del-componente works!
</p>
<p>
{{ dato }}
</p>
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 51 de 113
PuedesabrireseHTMLycolocarcualquiercosaqueconsideres,simplementeamododeprueba,para
comprobarqueconsiguesveresetextoahoracuandousemoselcomponente.
Nota:Nohemosentradotodavía,peroseguroquealgunoyaselopreguntaoquieresaberlo.El
componentetieneunarchivoCSS(aunquesepuedendefinirvarioseneldecoradordelcomponente)y
podemoseditarloparacolocarcualquierdeclaracióndeestilos.Veremosmásadelante,opodrás
comprobarportimismo,queesosestilosCSSseaplicanúnicamentealcomponentedondeestás
trabajandoynoaotroscomponentesdelaaplicación.
Conestohemosterminadodeexplicartodolorelativoalacreacióndeuncomponente.Elcomponente
estáahíyestamossegurosqueestarásansiosoporusarloentuproyecto.Esalgoqueveremosyamismo,en
elpróximoartículodelManualdeAngular2.
EsteartículoesobradeAlbertoBasalo
Fuepublicadoporprimeravezen26/08/2016
Disponibleonlineenhttp://desarrolloweb.com/articulos/crear-componente-nuevo-angular2.html
UsaruncomponenteenAngular2
CómoseusancomponentescreadospornosotrosenAngular2,unatareaquesibienessencilla
requieredevariospasos.
EnelpasadoartículorealizamostodoslospasosparacrearuncomponenteenAngular2.Realmentevimos
quelamayoríadelcódigologenerasdesdeAngularCLI,loqueaceleramuchoeldesarrolloyfacilitanuestra
labor.
Ahora,paraterminarnuestrapráctica,vamosaaprenderausarelcomponentequeacabamosdecrear.Es
unatareasencilla,perodebidoalaarquitecturadeAngularyelmododetrabajoquenosmarca,esalgoque
tendremosquerealizarenvariospasos:
1.CrearelHTMLparausarelcomponente
Enellugardelaaplicacióndondelovayasausarelcomponente,tienesqueescribirelHTMLnecesario
paraquesemuestre.ElHTMLnoesmásquelaetiquetadelcomponente,quesehadefinidoenlafunción
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 52 de 113
decoradora,atributo"selector"(comovimosalexplicarlosdecoradores).
<app-nombre-del-componente></app-nombre-del-componente>
DadoqueestamoscomenzandoconAngular2yelanterioreraelprimercomponentecreadopornosotros
mismos,sololopodreamosusardentrodelcomponenteprincipal(aquelgeneradoporAngularCLIalhacer
construirelnuevoproyecto).Aunquepuederesultarobvio,esaetiquetalatienesquecolocardentrodel
templatedelcomponenteprincipal.
ElHTML(template)deestecomponenteprincipalloencontramosenelarchivo"app.component.html".
Enesearchivo,lavistadelcomponenteprincipal,debemoscolocarlaetiquetaparapermitirmostrarel
componentereciéncreado.
Nota:Además,elcomponentesecreódentrodelmóduloprincipal.Nohabráproblemaenusarlo
dentrodelcomponenteraíz,quetambiénsecreódentrodelmóduloprincial(app.module.ts).Silo
quisierasusarenotrosmódulosolohubierascreadoenotrosmódulos,aestaoperativahabríaque
añadiralgúnpasoextra.Todoesoloveremoscuandonospongamosaexplicarlosmódulos.
Elproblemaesqueesaetiquetanoesconocidaporelnavegador.LasoluciónlaaportaAngular,yelcódigo
delcomponentedesarrolladoenelartículoanterior,dedicadoalacreacióndetuprimercomponente.Sin
embargo,paraqueestecomponenteseconozca,debesimportarloconvenientemente.Esloquehacemosen
lossiguientespasos.
2.Importarelcódigodelcomponente
Comodecíamos,parapoderusaruncomponentesedebedeconocersucódigo.Paraellotenemosque
realizarloscorrespondientesimport.LabuenanoticiaesqueAngularCLIhahechoeltrabajodemanera
automática.Anoserquequierasusarestecomponentedesdeotrosmódulos,tareaqueveremosmás
adelantecuandolleguemosamódulos,nonecesitasrealizarningúnimportadicional.
Noobstante,parafamiliarizarnosconelcódigo,yporsitenemosqueeditarlonosotrosmanualmentea
posteriori,vamosaidentificarenelmóduloprincipal"app.module.ts"lospuntosdondesehaimportadoel
códigodeestecomponentereciéncreado.
import { NombreDelComponenteComponent } from './nombre-del-componente/nombre-del-componente.component';
Eseimportindicaquetequierestraerlaclasedelcomponente"NombreDelComponenteComponent"y
despuésdel"from"estálarutadesdedondetelatraes.
Nota:Recuerdaquenonecesitasdecirlelaextensióndelarchivodondeestálaclase
NombreDelComponenteComponent.Setratadeunarchivo.tsygeneralmentelosarchivosTypeScript
norequierenqueindiquessuextensiónalimportarlos.
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 53 de 113
3.Declararquevasausarestecomponente
Elimportpermiteconocerelcódigodelcomponente,perotodavíanoessuficienteparapoderusarlo.
Debemosañadirloalarrayde"declarations"(tareaquetambiénhahechoAngularCLIdemanera
automática.
Enelmóduloprincipal,dondevasausarelcomponentedemomento,encuentraslafuncióndecoradoradel
módulo"@NgModule".Enesafuncióndebesdeclarartodosloscomponentesqueestemóduloestá
declarando,enelarray"declarations".
declarations: [
AppComponent,
NombreDelComponenteComponent
],
Eldecoradorcompletodelmóduloprincipalseveríaparecidoaesto:
@NgModule({
declarations: [
AppComponent,
NombreDelComponenteComponent
],
imports: [
BrowserModule
],
providers: [],
bootstrap: [AppComponent]
})
Observaqueelarray"declarations"mepermitedeclararquevoyausarvarioscomponentes.Simplemente
separosusnombresporcomas.Loqueindico,comopodrásapreciar,eselnombredelaclasedel
componentequepretendousar.Esaclaseeslaquehasimportadoconelcorrespondiente"import"delpaso
anterior(punto2).
Yesoestodo!Alguardarlosarchivossedeberíarecargardenuevolaaplicaciónenelnavegadorydeberías
verelHTMLescritoparaelcomponentequeestásusandoyqueacabamosdecrear.
ConclusiónalaintroduccióndeloscomponentesenAngular
ConesteartículohemoscompletadoelciclodeintroducciónaloscomponentesenelframeworkJavascript
Angular.Hemosreconocidosuspartesbásicas,hemoscreadouncomponentepropioylohemosusadoen
nuestraaplicación.
Elprocesopuedepareceruntantolaborioso,peroafortunadamenteAngularCLItelofacilitabastante.A
medidaquesevayarepitiendoobservaremosquenoestancomplicado.Lapartemásaburridadeescribirde
uncomponente,elesqueletooscaffoldingylosimports,yatelodanhechograciasaAngularCLI.Asíque
nosquedasimplementehacerlapartedelcomponentequecorrespondealasnecesidadesdelaaplicación.
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 54 de 113
ConlosconocimientosquehemosidoproporcionandoenlosanteriorescapítulosdelManualdeAngular2,
estamossegurosdequepodráscolocarmáscódigo,tantoenelHTMLcomoenlaclasedelcomponente
paraponerenprácticaloaprendido.
EsteartículoesobradeAlbertoBasalo
Fuepublicadoporprimeravezen31/08/2016
Disponibleonlineenhttp://desarrolloweb.com/articulos/usar-componente-angular2.html
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 55 de 113
LobásicodelosmódulosenAngular
Vamosahoraaabordarlasbasesdeotrodelosactoresprincipalesdelasaplicacionesdesarrolladascon
Angular:losmódulos.Unmódulo(moduleeninglés)esunareunióndecomponentesyotrosartefactos
comodirectivasopipes.Losmódulosnossirvenprincipalmenteparaorganizarelcódigodelasaplicaciones
Angularyportantodebemosaprenderautilizarlosbien.
TrabajarconmódulosenAngular
Cómocrearmódulos,agrupacionesdecomponentes,directivasopipes,enelframeworkJavascript
Angular.Cómocrearcomponentesdentrodeunmóduloycómousarlosenotrosmodules.
Unmóduloesunodeloselementosprincipalesconlosquepodemosorganizarelcódigodelasaplicaciones
enAngular.NodebenserdesconocidoshastaestemomentodelManualdeAngular,puestoquenuestra
aplicaciónbásicayadisponíadeuno.
Sinembargo,enlugardecolocarelcódigodetodosloscomponentes,directivasopipesenelmismo
móduloprincipal,loadecuadoesdesarrollardiferentesmódulosyagrupardistintoselementosenunosu
otros.Elordenserealizarádeunamaneralógica,atendiendoanuestraspropiaspreferencias,elmodelode
negocioolaspreferenciasdelequipodedesarrollo.
Enesteartículoaprenderásatrabajarconmódulos,realizandooperativasbásicascomocrearmódulosy
colocarcomponentesenellos.
Crearunnuevomódulo
ParafacilitarlastareasdecreacióndemódulosnosapoyaremosenelAngularCLI.Elcomandopara
generaresemódulonuevoes"generate"yacontinuacióntenemosqueindicarquéesloquesequiere
generar,enestecaso"module",acabandoconelnombredelmóduloacrear.
ng generate module nombre
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 56 de 113
Unavezlanzadoestecomandoennuestroproyecto,dentrodelacarpeta"src/app"secreaunsubdirectorio
conelmismonombredelmódulogenerado.Dentroencontraremosademáselarchivoconelcódigodel
módulo.
Nota:tantodaqueenelcomadonombreselmódulocomo"nombre"o"Nombre"(conlaprimeraen
mayúscula).ElCLIaplicalasconvencionesdenombresmásadecuadasycomolosmódulossonclases,
internamentelescolocaenelcódigolaprimeraletrasiempreenmayúscula.Yalosnombresdelos
directoriosyarchivosesotracosaynoserecomiendausarmayúsculas,porloquelosnombrarácon
minúsculasiempre.
Ahora,siabrimoselcódigodelmódulogenerado"nombre.module.ts",encontraremoscómosedefineun
móduloenAngular.Lapartemásimportantees,comoyavienesiendohabitualenAngular,undecorador.
Eldecoradordelosmódulossellama@NgModule.
@NgModule({
imports: [
CommonModule
],
declarations: []
})
Nota:esteeselcódigogeneradodeunmóduloconelCLIparaAngular4.Entucasopuedetener
algunasdiferencias,dependiendodelaversióndeAngularconlaqueestéstrabajando.
Comoveseneldecorador,tienesdemomentounpardearraysdefinidos:
imports:conlosimportsqueestemódulonecesita
declarations:conloscomponentes,uotrosartefactosqueestemoduleconstruye.
Generaruncomponentedentrodelmódulo
Ahoraquetenemosnuestroprimermódulopropio,vamosaagregaralgoenél.Básicamentecomenzaremos
porañadirleuncomponente,usandocomosiempreelAngularCLI.
Hastaahoratodosloscomponentesquehabíamoscreadohabíansidogeneradosdentrodelmódulo
principal,perosiqueremospodemosespecificarotromódulodondecrearlos,medianteelcomando:
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 57 de 113
ng generate component nombre/miComponente
Estonosgeneraráunacarpetadentrodelmóduloindicado,enlaquecolocarátodoslosarchivosdel
componentereciéncreado.
Nota:enestecasopuedesobservarcomohemoscolocadoenelnombredelcomponenteuna
mayúscula"miComponente",parasepararpalabrascomoen"camelCase".Porhaberlohechoasí,
AngularCLIhanombradoelarchivoseparandolaspalabrasporguiones"mi-
componente.component.ts".Porsuparte,podrásapreciarenelcódigoquelaclasedelcomponente,se
colocaconPascalCase,comomandanlasguíasdeestilosparaclases(classMiComponenteComponent).
Peroademás,elcomandodelCLItambiénmodificaráelcódigodelmódulo,agregandoautomáticamenteel
importdelcomponenteysureferenciaenelarray"declarations".Ahoraelcódigodelmódulo"nombre-
modulo.module.ts"tendráunaformacomoesta:
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { MicomponenteComponent } from './micomponente/micomponente.component';
@NgModule({
imports: [
CommonModule
],
declarations: [
MiComponenteComponent
]
})
export class NombreModuloModule { }
Exportardelmódulohaciaafuera
Másadelante,siqueremosqueestemóduloexpongacosashaciaafuera,quesepuedanllegarautilizardesde
otrosmódulos,tendremosqueagregarunanuevainformaciónaldecoradordelmódulo:elarraydeexports.
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 58 de 113
Vamosasuponerqueelcomponente"MiComponenteComponent"queremosquesepuedausardesde
otrosmódulos.Entoncesdebemosseñalarelnombredelaclasedelcomponenteenelarrayde"exports".
Conelloeldecoradordelmodulequedaríadeestamanera.
@NgModule({
imports: [
CommonModule
],
declarations: [
MiComponenteComponent
],
exports: [
MiComponenteComponent
]
})
Usarelcomponenteenotrosmódulos
ElúltimopuntoquenosquedaporverescómousarelcomponenteMiComponenteComponentdesde
otrosmódulos.Paraellovamosamodificarmanualmenteelmóduloprincipaldelaaplicación,demodoque
puedaconocerelcomponentedefinidoenelmódulonuevoquehemoscreadoenesteartículo.
Paraimportarelcomponenterealmenteloquevamosaimportareselmóduloenterodondesehacolocado,
yaqueelpropiomódulohaceladefinicióndeaquelloquesequiereexportaren"exports".Requierevarios
pasos
HacerelimportdelmóduloconlasentenciaimportdeJavascript
ParaqueJavascript(oenestecasoTypeScript)conozcaelcódigodelmódulo,debemosimportarloprimero.
EstonoesalgodeAngular,sinodelpropiolenguajeenparticular.
import { NombreModule } from './nombre/nombre.module';
Declararelimporteneldecoradordelmoduleprincipal
Laimportacióndenuestromóduloserealizaenladeclaración"imports"delmóduloprincipal.
Esteeselcódigodeldecoradordelmóduloprincipal.
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
NombreModule
],
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 59 de 113
providers: [],
bootstrap: [AppComponent]
})
Tetienesquefijarenelarrayimports,quetieneelmóduloquehemoscreadonosotrosmismoseneste
artículo"NombreModule".
UsarelcomponenteenHTML
Finalmenteyasolonosquedausarelcomponente.Paraellovamosacolocareneltemplatedelcomponente
raízelselectordeclaradoenelcomponentecreado.
Nota:recuerdaqueelselectordelcomponenteeseltagoetiquetaquesedebeusarparapoderusarun
componente.Estoyasedetallóanteriormenteenestemanual.Sinolorecuerdasoquieresmás
informaciónleeelartículoDecoradordecomponentesenAngular2.
Asíquesimplementeabrimoselarchivo"app.component.ts"ycolocamoslaetiquetadenuestronuevo
componentegenerado.
<app-mi-componente></app-mi-componente>
Esoestodo,siservimosnuestraaplicacióndeberíamosverelmensajedelcomponentefuncionando,quede
manerapredeterminadaseríaalgocomo"mi-componenteworks!".
Sinolovemos,onovemosnada,entoncesnostenemosquefijarelerrorquenosaparece,quepodríaestar
visibleenlapantalladelterminaldondehemoshechoel"ngserve",oenlaconsoladeJavascriptdetu
navegador.Posiblementeallítedigaquetalcomponentenoseconoce,conunmensajecomo"parseerrors:
'app-mi-componente'isnotaknownelement...".Esoquieredecirquenohashechoelimport
correctamenteeneldecoradordelmóduloprincipal.Obienquetehasolvidadodehacerelexportsdel
componenteausar,enelmóduloreciéncreado.
EsteartículoesobradeMiguelAngelAlvarez
Fuepublicadoporprimeravezen20/10/2017
Disponibleonlineenhttp://desarrolloweb.com/articulos/trabajar-modulos-angular.html
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 60 de 113
DirectivasesencialesdeAngular
Vamosaconoceralgunasdirectivasesencialesofrecidasporelpropioframework,paraeldesarrollodelas
vistasenAngular.
DirectivangClassenAngular2
EstudiodeladirectivangClassdeAngular2,ejemploprácticodeuncomponentequeusaesa
directiva.
DespuésdevariosartículosuntantodensosdeenelManualdeAngular2vamosaestudiaralgunascosas
unpocomásligeras,quenospermitiránpracticarconelframeworksinañadirmuchacomplejidadaloque
yaconocemos.ParaellovamosahacerunaseriedepequeñosartículosacercadelasdirectivasdeAngular2
másútileseneldíaadíadeldesarrollodeaplicaciones.
ComenzamosconladirectivangClass,quenospermitealterarlasclasesCSSquetienenloselementosdela
página.LoveremosenelmarcodeldesarrollodeaplicacionesAngularconunejemplobásico.
SivienesdeAngular1.xverásquelasdirectivashanperdidounpocodeprotagonismoeneldesarrolloen
Angular2.Muchasdelasantiguasdirectivashandesaparecidoysuusohasidosustituidoporotras
herramientasdiversas.ComonormaahoraenAngular2lasdirectivasseusaránparasolucionarnecesidades
específicasdemanipulacióndelDOMyotrostemasestructurales.
Nota:Loscomponentestambiénpuedenserconsideradoscomountipodedirectiva,aunqueeneste
casoseusanpararesolverproblemasdenegocio,comoyaseintrodujoenelartículosobrelas
característicasbásicasdeloscomponentes.
NotodoslosproblemasdeclasessenecesitanresolverconngClass
LoprimeroesdecirqueladirectivangClassnoesnecesariaentodosloscasos.Lascosasmássimplesni
siquieralanecesitan.Elatributo"class"delasetiquetassiloponesentrecorchetesfuncionacomo
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 61 de 113
propiedadalaquelepuedesasignaralgoquetengasentumodelo.Estolovimosenelartículosobrela
sintaxisdelasvistas.
<h1 [class]="claseTitular">Titular</h1>
Enestecaso,"claseTitular"esunavariabledelmodelo,algoquemepasaelcontroladorquetendrás
asociadoauncomponente.
export class PruebaComponent implements OnInit {
claseTitular: string = "class1";
cambiaEstado() {
this.claseTitular = "class2"
}
ngOnInit() {
}
}
LaclassdelH1valdráloquehayaenlavariableclaseTitular.Cuandoalguienllamealmétodo
cambiaEstado()semodificaríaelvalordeesavariableyportantocambiaríalaclaseenelencabezamiento.
Siestoyaresuelvelamayoríadelasnecesidadesquesenosocurren¿paraquésirveentoncesngClass?
AsignarclasesCSSconngClass
LadirectivangClassesnecesariapara,deunamaneracómodaasignarcualquierclaseCSSentreungrupode
posibilidades.Puedesusarvariosvaloresparaexpresarlosgruposdeclasesaplicables.Esparecidoacomo
funcionabaenAngular1.x.
Aestadirectivaleindicamoscomovalor:
1.Unarrayconlalistadeclasesaaplicar.EsearraylopodemosespecificardemaneraliteralenelHTML.
<p [ngClass]="['negativo', 'off']">Pueden aplicarse varias clases</p>
Oporsupuestopodríaserelnombredeunavariablequetenemosenelmodeloconelarraydeclases
creadomedianteJavascript.
<p [ngClass]="arrayClases">Pueden aplicarse varias clases</p>
EsearraylopodríashaberdefinidodelladodeJavascript.
clases = ['positivo', 'si'];
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 62 de 113
2.Unobjetoconpropiedadesyvalores(loqueseríaunliteraldeobjetoJavascript).Cadanombrede
propiedadesunaposibleclaseCSSquesepodríaasignaralelementoycadavaloresunaexpresiónquese
evaluarácondicionalmenteparaaplicaronoesaclase.
<li [ngClass]="{positivo: cantidad > 0, negativo: cantidad < 0, off: desactivado, on: !desactivado }">Línea</li>
EjemplodeaplicacióndengClass
Vamosahacerunsencilloejemplodeuncomponentellamado"BotonSino"quesimplementemuestraun
mensaje"SI"o"NO".Alpulsarelbotóncambiaelestado.Cadaestadoserepresentaademásconunaclase
queaplicaunaspecto.
Nota:Novamosaexplicarlaspartesdelcomponenteporquesevieroncondetalleenlosartículos
anterioresdelManualdeAngular2.Consultartodalapartededesarrollodecomponentesparamás
información.
NuestroHTMLeselsiguiente:
<p>
<button
[ngClass]="{si: estadoPositivo, no: !estadoPositivo}"
(click)="cambiaEstado()"
>{{texto}}</button>
</p>
Laetiquetabuttontieneunpardeatributosquesonlosquehacenlamagia.Entrecorchetesseaplicala
directiva"ngClass",conunvalordeobjeto.Entreparéntesisseaplicaelevento"click",conlainvocaciónde
lafunciónencargadadeprocesarlaacción.Además,eltextodelbotónesalgoquenosvendrádelavariable
"texto".
NuestroJavascriptseráelsiguiente:
import { Component, OnInit } from '@angular/core';
@Component({
moduleId: module.id,
selector: 'app-boton-sino',
templateUrl: 'boton-sino.component.html',
styleUrls: ['boton-sino.component.css']
})
export class BotonSinoComponent implements OnInit {
texto: string = "SI";
estadoPositivo: boolean = true;
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 63 de 113
cambiaEstado() {
this.texto = (this.estadoPositivo) ? "NO" : "SI";
this.estadoPositivo = !this.estadoPositivo;
}
ngOnInit() {
}
}
Comosabes,estecódigoTypeScripteslamayoríageneradoporAngularCLI.Loquehemoshecho
nosotrosesloqueestádnetrodelaclaseBotonSinoComponent.
Enellacreamoslaspropiedadesnecesariasenlavistayelmétodoqueseencargadeprocesarelcambiode
estado.
NuestroCSS:
Lógicamente,paraqueestofuncionenecesitaremosdeclararalgunosestilossencillos,almenoslosdelas
clasesqueseusanenelHTML.
button {
padding: 15px;
font-size: 1.2em;
border-radius: 5px;
color: white;
font-weight: bold;
width: 70px;
height: 60px;
}
.si{
background-color: #6c5;
}
.no{
background-color: #933;
}
Conestoestodo!EsunejemplomuysencilloquequizásparalosquevienendeAngular1.xresulte
demasiadobásico,peroseguroqueloagradeceránquienesesténcomenzandoconAngularenestos
momentos.Másadelantelocomplicaremosalgo.Realmenteladificultadmayorpuedeserseguirlospasos
paralacreacióndelcomponenteyluegolospasosparasuutilización,peroesoyalohemosexplicado
anteriormente.
EsteartículoesobradeMiguelAngelAlvarez
Fuepublicadoporprimeravezen13/09/2016
Disponibleonlineenhttp://desarrolloweb.com/articulos/directiva-nglass-angular2.html
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 64 de 113
DirectivangFordeAngular2
ExplicamosladirectivangFor,o*ngFor,quenospermiterepetirunaseriedevecesunbloquede
HTMLenaplicacionesAngular2.
EnesteartículovamosaconocerypracticarconunadirectivadelasmásimportantesenAngular2,quees
ladirectivangFor,capazdehacerunarepeticióndeelementosdentrodelapágina.Estarepeticiónnos
permiterecorrerunaestructuradearrayyparacadaunodesuselementosreplicarunacantidadde
elementosenelDOM.
ParalosquevengandeAngular1lessonará,puestoqueeslomismoqueyaseconocedengRepeat,aunque
cambianalgunascosillassobrelasintaxisparalaexpresióndelbucle,asícomoalgunosmecanismoscomola
ordenación.
UsobásicodengFor
Paraverunejemplodeestadirectivaenfuncionamientoestamosobligadosacreardeantemanounarray
condatos,quedebenserenviadosalavista,paraqueyaenelHTMLsepuedarealizaresarepetición.Como
todoenAngular2seorganizamedianteuncomponentes,vamosacrearuncomponentequecontienelo
necesarioparapoderusarestaelngFor.
ComenzamosconelcódigodelapartedeTypeScript,queesdondetendremosquecrearlosdatosque
estarándisponiblesenlavista.
import { Component, OnInit } from '@angular/core';
@Component({
moduleId: module.id,
selector: 'app-listado-preguntas',
templateUrl: 'listado-preguntas.component.html',
styleUrls: ['listado-preguntas.component.css']
})
export class ListadoPreguntasComponent implements OnInit {
preguntas: string[] = [
"¿España ganará la Euro 2016?",
"¿Hará sol el día de mi boda?",
"¿Estás aprendiendo Angular 2 en DesarrolloWeb?",
"¿Has hecho ya algún curso en EscuelaIT?"
];
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 65 de 113
ngOnInit() {
}
}
Estecódigonosdebedesonar,pueseselboilerplatedeuncomponente(creadomedianteAngularCLI)al
quelehemosagregadoladeclaracióndeunapropiedaddetipoarraydestrings.
Nota:Hemosasignadoelvalordeesearraydemaneraliteral,perolonormalseríaqueloobtengasde
algunafuentecomounservicioweb,API,etc.
Luego,veamoselcódigoHTMLdeestecomponente,queesdondecolocamosladirectivangFor.
<p *ngFor="let pregunta of preguntas">
{{pregunta}}
</p>
Esalgomuysencillo,simplementetenemosunpárrafoqueserepetiráunnúmerodeveces,unaporcada
elementodelarraydepreguntas.Enestecasoesunpárrafosimple,perosidentrodeéltuviéramosmás
elementos,tambiénserepetirían.Loquetenemosqueanalizarcondetalleeselusodeladirectiva,aunque
creemosqueseauto-explicaperfectamente.
*ngFor="let pregunta of preguntas"
Loprimeroqueverásesunsímboloasterisco(*)quequizásparezcaunpocoextraño.Noesmásque
"azúcarsintáctico"pararecordarnosqueestasdirectivas(lascomenzadasporelasterisco)afectanalDOM,
produciendolainserción,manipulaciónoborradodeelementosdelmismo.
Nota:EnlasexplicacionesqueencontrarásenladocumentacióndeAngular2sobreelorigendel
asteriscoenelnombredeladirectivanosmencionandetallesacercadesuimplementaciónabajonivel,
indicandoqueparaellosebasaneneltagTEMPLATE,unodelasespecificacionesnativasdeWeb
Components.
Comovalordeladirectivaverásquesedeclarademanerainternaparaestebucleunavariable"pregunta",
quetomarácomovalorcadaunodelosvaloresdelarrayencadaunadesusrepeticiones.
Nota:"let"esunaformadedeclararvariablesenJavascriptES6.Quieredecirqueaquellavariablesólo
tendrávalidezdentrodelbloquedondesedeclara.Enestecaso"demanerainterna"nosreferimosaque
"pregunta"solotendrávalidezenlaetiquetaquetieneelngForycualquieradesusloselementoshijo.
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 66 de 113
RecorridoaarraysconobjetosconngFor
GeneralmentengForlousaráspararecorrerarraysqueseguramentetendráncomovalorencadaunadesus
casillasunobjeto.Estonocambiamuchoconrespectoaloqueyahemosvistoenesteartículo,perosíes
unabonitaoportunidaddeaprenderalgonuevoconTypeScript.
DemomentoveamoslascosassinTypeScriptparairprogresivamente.Asíseríacómoquedaríala
declaracióndenuestroarray,alquetodavíanoindicaremoseltipoparanoliarnos.
preguntasObj = [
{
pregunta: "¿España ganará la Euro 2016?",
si: 22,
no: 95
},
{
pregunta: "¿Estás aprendiendo Angular 2 en DesarrolloWeb??",
si: 262,
no: 3
},
{
pregunta: "¿Has hecho ya algún curso en EscuelaIT??",
si: 1026,
no: 1
}
]
Comoves,loqueanteseraunarraydestringssimpleshapasadoaserunarraydeobjetos.Cadaunodelos
objetosnosdescribentantolapreguntaensícomolasrespuestaspositivasynegativasquesehanrecibido
hastaelmomento.
Ahora,alusarloenlavista,elHTML,podemosmostrartodoslosdatosdecadaobjeto,conuncódigoque
podríaserparecidoaeste:
<p *ngFor="let objPregunta of preguntasObj">
{{objPregunta.pregunta}}:
<br>
<span class="si">Si {{objPregunta.si}}</span> /
<span class="no">No {{objPregunta.no}}</span>
</p>
Comovesenestecódigo,dentrodelpárrafotengoaccesoalapregunta,quealserunobjeto,contiene
diversaspropiedadesqueusoparamostrarlosdatoscompletosdecadaitem.
ModificaciónimplementandoInterfacesTypeScript
Comohasvisto,noexistemuchadiferenciaconrespectoaloqueteníamos,peroahoravamosadarleun
usoaTypeScriptquenospermitiráexperimentaralgoquenosaportaellenguaje:interfaces.
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 67 de 113
Enestecasovamosausarlasinterfacessimplementeparadefiniruntipodedatosparalaspreguntas,un
esquemaparanuestrosobjetospregunta.Enestecasosololovamosausarparaque,alahoradeescribir
código,eleditornospuedaayudarindicandoerroresencasoquelainterfaznosecumpla.Así,alahorade
escribircódigopodremosestarsegurosquetodaslaspreguntasconlasquetrabajemostenganlosdatosque
sonnecesariosparalaaplicación.
Nota:Lasinterfacesquesesabesonmecanismosparasolventarlascarenciasdeherenciamúltiple,en
estecasolasvamosausarcomounasimpledefinicióndetipos.
Algotansencillocomoesto:
interface PreguntasInterface {
pregunta: string;
si: number;
no: number;
}
PermiteaTypeScriptconocerelesquemadeunobjetopregunta.Ahora,apoyándonosenesainterfaz
podrásdeclarartuarraydepreguntasdeestamanera.
preguntasObj: PreguntasInterface[] = [
{
pregunta: "¿Te gusta usar interfaces?",
si: 72,
no: 6
}
]
Ahoraestamosindicandoeltipodeloselementosdelarray,diciéndolequedebeconcordarconlodefinido
enlainterfaz.¿Tegusta?Quizásahoranoapreciesmuchadiferencia,peroestosepuedeusarparavarias
cosas,significandounaayudaenlaetapadedesarrollo,ysinafectaralrendimientodelaaplicación,puesto
quelasinterfacesenTypeScriptunaveztranspiladoelcódigonogenerancódigoalgunoenJavascript.
Nota:Lonormalesquecoloqueselcódigodelainterfazenunarchivoindependienteyquehagasel
correspondiente"import".RecordandoqueAngularCLItieneuncomandoparagenerarinterfacesque
tepuederesultarútil.Demomentosilodeseas,amododepruebalopuedescolocarenelmismo
archivoqueelcódigoTypeScriptdelcomponente.
QuizásparalosquenoesténacostumbradosaTypeScriptseadifícilhacerseunaideaexactasobrecómote
ayudaríaeleditordecódigoporelsimplehechodeusaresainterfaz.Parailustrarlohemoscreadoestevídeo
enelquemostramoslasayudascontextualescuandoestamosdesarrollandoconVisualStudioCode.
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 68 de 113
Paraverestevídeoesnecesariovisitarelartículooriginalen:
http://desarrolloweb.com/articulos/directiva-ngfor-angular2.html
Hablaremosmássobreinterfacesenotrasocasiones.Ahoraelobjetivoerasimplementeverunapequeña
muestradelasutilidadesquepodríaaportarnos.
Comohabrásvistonoesdifícilentenderestadirectiva,perotenencuentaquehemosvistoloesencialsobre
lasrepeticionesconngFor.Haymuchomásquehabríaquecomentarenunfuturo,acercadeusosunpoco
másavanzadoscomopodríaserlaordenacióndeloselementosdellistado.
EsteartículoesobradeMiguelAngelAlvarez
Fuepublicadoporprimeravezen27/09/2016
Disponibleonlineenhttp://desarrolloweb.com/articulos/directiva-ngfor-angular2.html
DirectivangModel
ExplicacionessobreladirectivangModeldeAngular,conejemplosdeusodiversos,conbinding
deunaydosdirecciones.ImportarFormsModuleparasufuncionamientoenAngular4.
LadirectivangModelesunviejoconocidoparalaspersonasquevienendelasversionesantiguasdel
framework,cuandosellamabaAngularJS.Quizásparaellosnorequieratantasexplicacionesdeconcepto,
aunquesíseráimportanteexplicarcómousarla,porquehancambiadobastantescosas.
Detodosmodos,tantoparadesarrolladoresexperimentadoscomoparalosmásnovatos,vamosarepasar
enesteartículodelManualdeAngularlosaspectosbásicosdengModelyveralgunosejemplossencillosde
funcionamientoencomponentes.
QuéesngModel
PensandoenlaspersonasquesonnuevasenAngular,tendremosquecomenzaraclarandoquéesngModel.
Básicamentesetratadeunenlace,entrealgoquetienesenladefinicióndelcomponenteconuncampode
formulariodeltemplate(vista)delcomponente.
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 69 de 113
Nota:"model"enngModelvienedeloqueseconocecomoelmodeloenelMVC.Elmodelotrabaja
conlosdatos,asíquepodemosentenderqueelenlacecreadoconngModelpermitequedesdelavista
puedausarundato.Sinembargo,conexpresionesyasepodíausarundato,volcandosuvalorenlavista
como{{dato}}.Ladiferenciaesquealusaresedatoencamposdeformulario,debesaplicarelvalor
medianteladirectivangModel.
Porejemplo,tenemosuncomponentellamado"cuadrado",quedeclaraunapropiedadllamada"lado".La
classdelcomponentepodríaquedarasí:
export class CuadradoComponent {
lado = 4;
}
Siqueremosqueesevalor"lado"sevuelquedentrodeuncampoINPUTdeformulario,tendríamosque
usaralgocomoesto.
<input type="number" [ngModel]="lado">
EstamosusandoladirectivangModelcomosifueraunapropiedaddelcampoINPUT,asignándoleelvalor
quetenemosdeclaradoenelcomponente.
DarsoportealapropiedadngModelenelcampodeformulario
Sinembargo,nuestrocomponente"cuadrado"nofuncionaríatodavía,porqueAngular4enprincipiono
reconocengModelcomopropiedaddeuncampoINPUTdeformulario.Porello,siejecutastuaplicación
conelcódigotalcomohemoshechohastaahora,obtendrásunmensajedeerrorcomoeste:"Can'tbindto
'ngModel'sinceitisn'taknownpropertyof'input'."
Lasoluciónpasaportraernosesapropiedad,queestáenelmódulo"FormsModule".
Paraellotenemosquehacerlaoperativatradicionaldeimportaraquelloquenecesitamos.Enestecaso
tendremosqueimportarFormsModuleenelmódulodondevamosacrearaquelcomponentedondese
quierausarladirectivangModule.
Porejemplo,sinuestrocomponente"CuadradoComponent"estáenelmódulo"FigurasModule",estesería
elcódigonecesarioparadeclararelimportde"FormsModule".
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { CuadradoComponent } from './cuadrado/cuadrado.component';
import { FormsModule } from '@angular/forms';
@NgModule({
imports: [
CommonModule,
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 70 de 113
FormsModule
],
declarations: [CuadradoComponent],
exports: [CuadradoComponent]
})
export class FigurasModule { }
Delcódigodelmóduloanterior,debesfijarteendoscosas:
1.-ElimportdeFormsModule,quevienede@angular/forms
import { FormsModule } from '@angular/forms';
2.-Ladeclaraciónenelarraydeimportsdelmóduloencuestión:
imports: [
[...]
FormsModule
],
ConestainfraestructurayasomoscapacesdeusarngModuleenlasvistasdeloscomponentesAngular.
EnlacedeunaodedosdireccionesconngModel
Talcomohemosdejadoelcódigohastaelmomentoenlavista,elinputestabaasociadoalvalordeuna
propiedaddelcomponente,sinembargo,eraunenlacedeunaúnicadirección.
<input type="number" [ngModel]="lado">
Conesasintaxisenlavista,loquehayaenlapropiedad"lado"seescribíacomovalordelinput,perono
encontramoseldoblebinding.Yaunqueestoesalgoqueyasetratóenelartículodesintaxisdelasvistasen
Angular,queremosrecordarque,paraespecificareldoblebinding,sedebeusarlasintaxis"bananaina
box".
<input type="number" [(ngModel)]="lado">
Ahora,loqueseescribaenelcampoINPUTtambiénviajaráhaciaelmodelo,actualizandoelvalordela
propiedad"lado"delcomponente.
EventongModelChange
Silodeseas,tambiéntienesdisponibleuneventollamado"ngModelChange"queseejecutacuandocambia
elvalorenlapropiedadasociadaaunngModel,conelquepodríamosconseguiruncomportamiento
idénticoalvistoenelpuntoanteriordeldoblebinding,perosinusarelbindingdoble.
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 71 de 113
TienesquetrabajarconngModelChangeenconjuntoconladirectivangModel.MediantengModelasocias
lapropiedadquequieresasociaryentoncestendráslaposibilidaddeasociarunmanejadordeeventoa
ngModelChange,cadavezqueesapropiedadcambia.
Dentrodelmanejadordeeventopodemosademásusarunavariablellamada$event,enlaquerecibimosel
nuevovalorescrito,quepodríamosvolcarladenuevoalapropiedadpormediodeunaasignación,para
conseguirelmismoefectodelbindingenlasdosdirecciones.Elcódigotequedaríacomoesto:
<input type="number" [ngModel]="lado" (ngModelChange)="lado = $event">
Nota:Estasintaxisnoaportaningunaventajaentérminosderendimiento,porloqueenprincipiono
sesueleusarmucho.Generalmentevamosapreferirusarlasintaxisdelbindingdedosdirecciones
[(ngModel)],porsermásconcisa.Detodosmodos,podríaserinteresantedisponerdengModelChange
enelcasoque,cuandocambiaseelmodelo,necesitasesrealizarotrasacciones,adicionalesalasimple
asignacióndeunnuevovalorenlapropiedaddelcomponente.
Ejemplorealizadoenesteartículo
Ahoraparalareferencia,voyadejarelcódigorealizadoparailustrarelcomportamientoyusodeladirectiva
ngModel.Estarácompuestoporvariosarchivos.
Vistadelcomponente:
Comenzamosconlavistadelcomponente,archivocuadrado.component.html,queeslomásimportanteen
estecaso,yaqueesellugardondehemosusadongModel.
Hecreadovariasversionesdeenlacealinput,comopuedesveracontinuación.
<p>
Tamaño del lado {{lado}}
</p>
<p>
1 way binding <input type="number" [ngModel]="lado">
</p>
<p>
2 way binding: <input type="number" [(ngModel)]="lado">
</p>
<p>
Evento ngModelChange: <input type="number" [ngModel]="lado" (ngModelChange)="cambiaLado($event)">
</p>
OtracosaqueapreciarásenlavistaesqueeleventongModelChangenotieneescritoelcódigodel
manejadorenlapropiavista,porconsiderarlounantipatrón.Esmásinteresantequeelcódigosecoloque
dentrodeunmétododelcomponente.Enestecasotendrásqueenviarlealmétodoelvalor$event,paraque
lopuedasusarallí.
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 72 de 113
CódigoTypeScriptdelcomponente:
Elcódigodelcomponenteestaráenelarchivocuadrado.component.tsynotieneningunacomplicaciónen
especial.
import { Component } from '@angular/core';
@Component({
selector: 'dw-cuadrado',
templateUrl: './cuadrado.component.html',
styleUrls: ['./cuadrado.component.css']
})
export class CuadradoComponent {
lado = 1;
cambiaLado(valor) {
this.lado = valor;
}
}
Módulodondesecreaelcomponente:
Porúltimorecuerdaqueesesencialqueimportesenelmódulodondeestéscreandoestecomponenteel
propiomódulodelcoredeAngulardondeseencuentraladirectivangModule.Estolohemosdescritoen
unbloqueanterior,perovolvemosacolocaraquíelcódigofuente:
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { CuadradoComponent } from './cuadrado/cuadrado.component';
import { FormsModule } from '@angular/forms';
@NgModule({
imports: [
CommonModule,
FormsModule
],
declarations: [CuadradoComponent],
exports: [CuadradoComponent]
})
export class FigurasModule { }
Porsupuesto,parapoderusarestecomponente"CuadradoComponent"enotromódulotendrásquehacer
elcorrespondienteimport,peroestoesalgoqueyasetratóenelartículodelosmódulosenAngular.
Nota:AdemásdelaaplicacióndengModelquehemosconocidoenesteartículo,relacionada
directamenteconelsistemadebindingdeAngular,ngModeltambiénsirveparadefinirquécamposde
formulariodebensertratadosalgenerarselosobjetosngForm.Estosobjetossecreanautomáticamente
yAngularlosponeadisposiciónparapodercontrolarelformulariodeunamaneramuyprecisa.Eseuso
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 73 de 113
loveremosmásadelantecuandohablemosendetalledelosformulariosdeAngular.
EsteartículoesobradeMiguelAngelAlvarez
Fuepublicadoporprimeravezen26/10/2017
Disponibleonlineenhttp://desarrolloweb.com/articulos/directiva-ngmodel-angular.html
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 74 de 113
BindingenAngularaldetalle
Enlossiguientesartículosvamosaexplorardetenidamenteelsistemadedata-bindingcreadoconAngular,
tratandoconprofundidadalgunostemasyausadosdentrodeestemanual,asícomoabordandonuevos
temasimportantesrelacionadosconelbindeodedatos.
Interpolación{{}}enAngularaldetalle
TodoloquetienesquesabersobreelbindingporinterpolacióndestringsenAngular,generada
conlasintaxisdelasdoblesllaves{{}}.
ConesteartículocomenzamosunaseriedeentregasdelManualdeAngularenlasquevamosaabordar
distintosaspectosdelbindingenesteframework.Sonimportantes,porqueapesardesercosasbásicas
muchasveceslasdejamospasaryesedesconocimientoacabacreandoconfusionesmásadelante.
Detodosmodos,novamosaexplicartododesdecero,yaquelasbasesdeldata-bindingyalashemos
conocidoenartículosanterioresdelmanual.Concretamenteesinteresantequehayasleídoelartículosobre
lasintaxisparalasvistasdecomponentes.
EnesteartículovamosatratarmuchascosassobrelainterpolaciónenAngularquequizáshemosdadopor
sentadasenartículosanterioresyquemerecelapenatratardemaneradetalladayclara.
Quéeslainterpolacióndestrings
Lainterpolacióndecadenas,tambiénconocidaeningléscomo"stringinterpolation",osimplementecomo
interpolación,esunmecanismodeAngulardesustitucióndeunaexpresiónporunvalordecadenaenun
template.
CuandoAngularveenuntemplatealgoescritoentredoblesllaves{{}}loevalúaylotratadeconvertiren
unacadena,paraluegovolcarloeneltemplate.
<p>Esto es un caso de interpolación de {{algunaCadena}}</p>
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 75 de 113
EsoquieredeciraAngularquedebesustituirunapropiedaddelcomponentellamada"algunaCadena"y
colocarsuvalortalcualeneltemplate.
Si"algunaCadena"esunacadena,simplementeseescribirásuvaloreneltemplate,perosiesonoerauna
cadenatratarádecolocarlodemaneraquelofuera.Porejemplo,situvieraunvalornuméricocolocaráel
númerotalcualeneltemplate.
PuedesusartambiénlainterpolacióncomovalordepropiedadesdeelementosHTML,comoeselsiguiente
caso.
<img src="{{urlImagen}}">
EnestecasosecolocaráelvalordelapropiedadurlImagencomosrcparaelelementoIMG.
Lainterpolaciónesdinámica.Quieredecirque,sicambiaelvalordelapropiedaddelcomponente,Angular
sedaráeltrabajodecambiartodosloslugaresdondeseestáhaciendousodeesapropiedad,loque
cambiaríaeltextoquehayescritodelpárrafoanterior,ocambiaríalaimagenqueseestávisualizandoenel
elementoIMGanterior.
Expresiones,entrelasdoblesllaves
Loquesecolocaentrelasdoblesllavessonllamadasexpresiones.Podemoscrearexpresionessimplesy
complejasyAngularsedaráeltrabajodeevaluarlasantesdevolcarelresultadodentrodeltemplate.
Loqueesimportanteesque,aquellaevaluacióndelaexpresión,debedeserconvertidaenunacadenaantes
devolcarseenuntemplate.Esdecir,cualquierexpresiónalfinaldecuentasseconvertiráenunacadenay
esoesloquesecolocaráenlavistadelcomponente.
Unaexpresiónpuedeseralgotansimplecomounapropiedaddelcomponente,comolasusadas
anteriormenteenesteartículo.
{{algunaCadena}}
EsasencillaexpresiónseevalúaalvalorquetengalapropiedadalgunaCadenaysevuelcaeneltemplate.
Tambiénpodemosverexpresionesconoperacionesmatemáticas.
{{ 1+ 1 }}
Expresionesconoperadorlógicodenegación:
{{ ! valorBoleano)
Inclusoexpresionescuyovalorescalculadoporunmétododelcomponente.
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 76 de 113
{{ metodoComponente() }}
Loquedevuelvaesemétododelcomponenteesloquesecolocaráeneltemplate.Esemétodosevolveráa
ejecutarcadavezqueelestadodelcomponentecambie,esdecir,cadavezquecambieunadesus
propiedades,produciendosiempreunasalidaactualizada.
Nota:aunquevamosainsistirsobreestepuntoyseentenderámejorsisigueslalecturadelartículo,hay
quedecirqueesemétodotienequelimitarseaproducirsalidayademássersencilloyrápidodeejecutar.
Estoevitaráafectarnegativamentealrendimientodelasaplicaciones.elmotivoessencillo:sidurantela
ejecucióndelaaplicaciónsemodificanlaspropiedadesdelcomponente,Angularvolveráaejecutarese
método,actualizandolasalidaconvenientemente.Esoseharáantecualquierpequeñocambioenel
componente,ynosoloantecambiosenlaspropiedadesconlasquetrabajeelmétodo,inclusose
producirásolamenteporhaberocurridouneventosusceptibledemodificarelestado.Siponesenel
métodocódigoquetardeenejecutarse,Alproducirsemuchasinvocacionesrepetidasaestemétodo,se
multiplicaráelcostedetiempodeejecución,produciendoquelaaplicacióncaigaenrendimientoy
afectandonegativamentealaexperienciadeusuario.
Losefectoslateralesestánprohibidosenlasexpresiones
LainterpolaciónenAngularesunenlace(binding)deunaúnicadirección.Cuandocambianlosvaloresen
elcomponenteviajanhaciaeltemplate,produciendolaactualizacióndelavista.
Lainterpolaciónnodeberíaproducircambiosenlaotradirección,esdecir,modificaralgoenlavista
afectandoalestadodelcomponente.Dichodeotromodo,lasexpresionesnuncadebencontenersentencias
quepuedanproducirefectoslaterales.Esdecir,códigoquepuedaafectaracambiosenlaspropiedadesde
componentes.
Tenencuentaquelasexpresionestienencomoutilidaddevolverunacadenaparavolcarlaeneltemplatedel
componente,porloquenodeberíascolocarlógicadenegocioenellas,manipulandovariableso
propiedadesdeestadodelcomponenteolaaplicación.
Porestedetalle,algunosoperadoresestánprohibidosenlasexpresiones,porejemplolosdeasignación,
incrementos,decrementos,etc.Porejemplo,nuncahagasalgocomoesto:
{{ valorBoleano = false }}
SiAngularobservaunaexpresiónconoperacionescapacesderealizarefectoslaterales,tedevolveráun
error,comoelquevesenlasiguienteimagen:
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 77 de 113
Porestemismomotivo,cuandodentrodeunaexpresióninvocasaunmétodo,nodeberíasmodificarenel
códigodeesemétododatosdelcomponentecapacesdeproducirefectoslaterales,sinosimplemente
limitarteaproducirunasalida.
{{ metodoProduceEfectosLaterales() }}
EnelcasoquemetodoProduceEfectosLaterales()tengacódigoqueproduzcacambioselelestadodel
componenteAngularnotelovaaadvertiryvaaejecutarelmétodosinproducirningúnmensajedeerror,
peroaunasínolodeberíashacer.Noessoloporceñirsealasbuenasprácticas,sinoporqueAngularno
tendráencuentaaquelcambioenelestadodelcomponenteparadesencadenarotrasoperacionesnecesarias,
loquepuedeproducirquetustemplatesnomuestranloscambiosenpropiedadesuotrosefectosno
deseables.
Otrasconsideracionesenlasexpresiones
Otrascosasqueestábiensabercuandoseusanexpresionessonlassiguientes:
Lasexpresionestienencomocontextoalcomponentedeltemplatequeseestádesarrollando.Pero
nopuedenaccederalcontextoglobal,comovariablesglobalesuobjetoscomodocumentowindow.
Tampocoacosasdelnavegadorcomoconsole.log().
Nosepuedenescribirestructurasdecontrol,comosentenciasif,for,etc.
Laejecucióndeunaexpresióndebeserdirecta.Porejemplonopodráshacerqueseconsulteun
APIRESTenunaexpresión.
Manténlasimplicidad.Cosascomousarunanegaciónenlaexpresiónescorrecto,perosiloque
tienesquecolocaresciertalógicacompleja,entoncesconvieneusarunmétodoenelcomponente.
Ofrecersiempreelmismoresultadoconlosmismosvaloresdeentrada.Estoseconocecomo
expresionesidempotentes,aquellasqueejecutadasvariasvecesdansiempreelmismoresultado.
Obviamente,silaentradaesdistintaylosdatosqueseusanparacalcularelvalordelaexpresión
cambian,elresultadotambiéncambiará,peroseguirásiendoidempotentesiconelmismojuegode
valoresdeentradaconseguimossiemprelamismasalida.Estoesnecesarioparaquelosalgoritmos
dedeteccióndecambiosdeAngularfuncionencorrectamente.
EsteartículoesobradeMiguelAngelAlvarez
Fuepublicadoporprimeravezen30/10/2017
Disponibleonlineenhttp://desarrolloweb.com/articulos/binding-interpolacion-angular.html
BindingapropiedadesenAngularaldetalle
Quéeselpropertybinding,juntoconunaseriededetallesimportantessobreelbindeoa
propiedadesquecomodesarrolladorAngulardebesconocer.
Aunqueyahemoshabladodelbindingdepropiedades,vamosavolversobreesteconceptopueshemos
pasadoporaltobastantesdetallesenlosquemerecelapenadetenerseconcalma.Setratadeuna
característicadisponibleeneldesarrollodetemplatesdeloscomponentes,quehemosvistoaplicadaalo
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 78 de 113
largovariosejemplosdelManualdeAngular,peroesperamospoderofreceralgunosconocimientosextra
queseguramentetevendránbien.
Comenzaremosrepasandodenuevoelconcepto,paraofrecerluegodiversasexplicacionesadicionalessobre
cómofuncionaelpropertybinding.Ademásresolveremosalgunasdudascomunesdelaspersonasquese
inicianenAngular.
Quéeselbindeoapropiedades
Elbindingapropiedades,o"propertybinding"eninglés,sirveparaasignarunvaloraunapropiedaddeun
elementodeuntemplate.Esaasignaciónpodráserunvalorliteral,escritotalcualeneltemplate,pero
generalmentesetratarádeunvalorobtenidoatravésdeunapropiedaddelcomponente,demodoquesiel
estadodelcomponentecambia,tambiéncambielapropiedaddelelementoasignadaeneltemplate.
Paraquenoquedelugaradudastenemosquedefinirexactamentequéesunapropiedad.Dehecho,enel
párrafoanteriorhemosusadolapalabra"propiedad"parareferirnosadoscosas,loquepuededarmayor
pieaconfusión.
Propiedadesdecomponentes
LoscomponentesgeneradosconAngularseimplementanmedianteunaclase,deprogramaciónorientadaa
objetos.Laspropiedadesdeesaclase,losdatosquealmacenaelcomponente,sonloquellamamos
"propiedadesdelcomponente".
Generalmenteenesteartículocuandonosreferimosa"propertybinding"nonosreferimosespecíficamente
apropiedadesdelcomponente,sinoapropiedadesexpresadasenuntemplate.Éstaspuedenser
propiedadesdeelementosHTML(propiedadesdelDOMdeesoselementos)opropiedadesde
componentesengeneral.
Propiedadesexpresadaseneltemplate
EnelHTMLdelcomponente,loquellamamoseltemplateolavista,laspropiedadessoncualquiercosaa
lasqueasignamosvalorespormediodebinding.Estolopodemosverbienconunejemplo.
AcontinuacióntieneselementosdelHTMLalosquedefinimosvalorespormediodeatributos.
<img src="imagen.jpg">
<button disabled>Estoy desactivado</button>
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 79 de 113
Aesosatributosdelasetiquetaslesasignamosvalores,quesirvenparainicializarloselementosHTML.
Debesdesaberdesobracómofuncionan.
Talcomoestán,esaetiquetaIMGoesebotóntendránsiempreelmismovalorensuspropiedades"src"y
"disabled".Sinembargo,siquisierasasignarunvalordinámicoaunodeesosatributos,tomandoalgo
definidomedianteunapropiedaddelcomponente,tendríasqueacudiralpropertybinding.Sedefineel
bindeoapropiedadmedianteunasintaxisespecialdeAngular,asuntodeesteartículo.
<img [src]="rutaImagen">
<button [disabled]="estadoBoton">Estoy activado o desactivado</button>
Enestecasoesdondeencontramoslaspropiedadesgenéricasalasquenoshacemosreferencia,aquellas
expresadaseneltemplateconlanotacióndeloscorchetesdeinicioydecierre.
Graciasalbindingdepropiedadestenemosunaimagenyunbotónigualmente,peroenlaimagensusrcse
calculaenfuncióndelapropiedaddelcomponentellamada"rutaImagen".Enelcasodelbotón,elestado
activoodesactivado,estádefinidoporlapropiedaddelcomponente"estadoBoton".
Loimportantequedebemosentenderes:cuandotrabajasconpropiedadesdeltemplate,noestásasignando
valoresaatributosdeHTML.Dehecho,alponerleloscorchetesdejandeseratributosdelHTMLpara
pasaraserpropiedadesdeltemplatedeAngular.
Variantesdelpropertybinding
Medianteloscorchetespuedesasignarvaloresdinámicosapropiedadesdeuncomponente,propiedadesde
directivas,oenelcasodeloselementosHTMLnativos,estásasignandovaloresdirectamentealDOM.
Vamosaanalizarmásdecercaestoscasosconvariosejemplos.
<img [src]="rutaImagen">
EnesteejemploestamoscolocandounvaloraunapropiedaddeunelementonativodelHTML,quenos
aceptaunstring.
Sinembargonotodaslaspropiedadesaceptancadenas,algunasaceptanboleanos,comoeraelcasodel
botón.
<button [disabled]="estadoBoton">Estoy activado o desactivado</button>
Esteesuncasointeresante,porqueelelementonativodelHTMLfuncionademododiferente.Sitieneel
atributo"disabled"estádesactivado.Sieseatributonoaparece,entoncesestaráactivado.Yaparadefinirel
valordelapropiedaddeAngularaparecerásiempreelatributo,peroenalgunasocasionesestarádesactivado
yenotrasactivado,dependiendodelvalordelavariableboleana"estadoBoton".
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 80 de 113
Tambiénpodemosencontrarbindingapropiedadesenunadirectiva,comosepuedeverenelsiguiente
código.
<div [ngStyle]="objEstilos">DIV con estilos definidos por Angular</div>
Enestecaso,mediantelapropiedad"objEstilos"seestádefiniendodinámicamenteelstyledeestadivisión.
Sicambiaelobjetocambiarálaaplicacióndelosestilosalelemento.
Porúltimo,tenemosasignaciónapropiedadespersonalizadasdenuestrospropioscomponentes.
<mi-componente [propiedadPersonalizada]="valorAsignado"></mi-componente>
Esteesuncasoespecial,queexplicaremoscondetallecuandohablemosdelaspropiedades@Inputde
componentes.Básicamentenospermitencrearcualquiertipodepropiedadencomponentes,quesomos
capacesdedefinirenelpadre.Enesecasoconcreto,mediantelapropiedaddelcomponentepadre
"valorAsignado"estamosaplicandoelvalordelcomponentehijoenlapropiedad"propiedadPersonalizada".
Bindingdeunadirección
Comosehamencionado,laasignacióndeunapropiedadesdinámica.Esdecir,sicambiaconeltiempo,
tambiéncambiarálaasignaciónalelementoalqueestamosbindeando.
Volvemosdenuevoalejemplo:
<img [src]="rutaImagen">
Alcrearselaimagensetomarácomovalordesu"src"loquehayaenlapropiedaddelcomponente
"rutaImagen".Siconeltiempo"rutaImagen"cambiadevalor,elvalorviajarátambiénalaimagen,
alterandoelarchivográficoquedichaimagenmuestra.
Propertybindingessiempredeunadirección,depadreahijo.Elpadredefineunvaloryloasignaalhijo.
Portanto,aunqueelhijomodificaseelvalornuncaviajaráalpadre.
Obviamente,asignandounvaloraun[src]deunaimagendichaimagennovaacambiarelvalor,peroenel
casodeuncomponentecreadopornosotrossíquepodríaocurrir.
<app-cliente [nombre]="nombreCliente"></app-cliente>
Enestecaso,elpadrehadefinidoqueelnombredelclientesealoqueéstetieneensupropiedad
"nombreCliente".Podríaocurrirqueelcomponenteapp-clientecambiaseelvalordesupropiapropiedad
"nombre".Siesoocurre,elcomponentepadrenonotaránadapordarseunbindingdeunaúnicadirección
(padresahijos).
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 81 de 113
Nota:Enbreveexplicaremoscómoesposiblecrearcomponentesqueaceptenvaloresdeentradaen
suspropiedades.Estoadelantamosquesehaceconeldecorador@Inputaldefinirlapropiedadenla
clasedelcomponente.
Valoresposiblesparaunapropiedad
Entrelascomillasasignadascomovaloraunapropiedadpodemoscolocarvariascosas.Locomúnesque
bindeemosmedianteunapropiedaddelcomponente,talcomosehavistoenejemplosanteriores,pero
podríamoscolocarotrocódigoTypeScript.
Así,dentrodelvalordeunapropiedad,podemosusarunpequeñoconjuntodeoperadorescomoelde
negación"!",igualqueteníamosenlasexpresionesenelbindingporinterpolacióndecadenas.
Ademásvamosaverunejemplointeresanteporquenosdarápieaexplicarotrascosas:podríamosbindeara
unliteral.
<img [src]="'ruta.jpg'">
Enestecaso"ruta.jpg"estáescritoentrecomillassimples,luegoesunliteraldestring.Quieredecirque
Angularloevaluarácomounacadena,loasignaráalapropiedadyseolvidarádeél.Estonotienemucho
sentido,yaquelopodríamoshaberconseguidoexactamenteelmismoefectoconelpropioatributoHTML,
sincolocarloscorchetes.
<img src="'ruta.jpg'">
Estaposibilidad(laasignacióndeunliteral)tendrámássentidoalusarloencomponentespersonalizados.
<app-cliente nombre="DesarrolloWeb.com"></app-cliente>
Alnocolocarlapropiedadentrecorchetes,escomohacerunbindingaunliteraldestring.Portanto,el
componenteapp-clienterecibiráelvalor"DesarrolloWeb.com"ensupropiedad"nombre"alinicializarse,
peronoseestableceráningúnbindingdurantesuexistencia.
Tambiénpodemosbindearaunmétodo,provocandoqueesemétodoseejecuteparaaplicarunvalorala
propiedadbindeada.
<p [ngClass]="obtenClases()">Esto tiene class o clases dependiendo de la ejecución de un método</p>
Enestecaso,cadavezquecambiecualquiercosadelestadodelcomponente,seejecutarádenuevo
obtenClases()pararecibirelnuevovalordeclasesCSSquesedebenaplicaralelemento.
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 82 de 113
Nota:ElcódigodetumétodoobtenClases()deberíasermuyconcisoyrápidodeejecutar,puestoque
suinvocaciónserealizarámuyrepetidasveces.Endefinitiva,debesusarloconcuidadoparanoafectaral
rendimientodelaaplicación.
Evitarefectoslaterales
DelmismomodoqueocurríaconlasexpresionesenlaInterpolacióndestrings,sedebeevitarqueal
evaluarelvalordeunapropiedadsecambieelestadodelcomponente.
Porejemplo,sienlaexpresiónaevaluarparadefinirelvalordeunapropiedadcolocasunaasignación,verás
unerrordeAngularadvirtiendoesteasunto.
<img [src]="ruta = 'ruta.jpg'">
Estoúltimonosepuedehacer.Angularsequejaráconunmensajecomo"emplateparseerrors:Parser
Error:Bindingscannotcontainassignments".
Tenencuentaque,albindearunapropiedadmedianteelvalordevueltoporunmétodo,Angularno
mostraráerroresfrenteaefectoslateralesproducidospormodificarelestadodelcomponente.Porejemplo
en:
<img [src]="calculaSrc()">
SiencalculaSrc()cometemoslaimprudenciademodificarelestado,Angularnoserácapazdedetectarloy
podremosencontrarinconsistenciasentrelaspropiedadesdelcomponenteyloqueseestámostrandoenel
template.
Demomentoestodoloquetienesquesabersobreelbindeodepropiedades.Enelsiguienteartículo
revisaremosotradelaspreguntasfrecuentesdelaspersonasquecomienzanconAngular,¿Cuándousar
interpolaciónobindeoapropiedades?.
EsteartículoesobradeMiguelAngelAlvarez
Fuepublicadoporprimeravezen09/11/2017
Disponibleonlineenhttp://desarrolloweb.com/articulos/binding-propiedades-angular.html
Bindingapropiedadvsinterpolacióndestrings,enAngular
Cuándousarelbindingdepropiedadolainterpolacióndestrings,dosalternativasconobjetivos
distintosenAngular,queavecespuedenconfundir.
EnesteartículovamosaanalizarencontraposicióndosalternativasdebindingenAngular,queaveces
puedenproducirdudas,básicamenteporquepodríanserusadasencontextossimilares.
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 83 de 113
Elobjetivoesayudarallectoraidentificarloscasosdondeserecomiendausarelbindeodepropiedadesola
interpolacióndestrings,demodoqueseacapazdeescogerlamejoropciónencadacaso.
Recuerdaqueestosconceptosyasehanexplicado,demodoquedeberíasconoceralmenosquédiferencias
tienen.Sinoesasíterecomendamosleerelartículosobrelainterpolacióndestringsyelbindingde
propiedades.
Dosmecanismosdistintos,quepuedenusarseensituacionesparecidas
Sabiendoquelainterpolacióndestringsyelbindingdepropiedadessoncosasbiendistintas,queremos
mostrarqueenocasionespuedenserusadasenlosmismoslugares,produciendoidénticoresultado.
Observemoselsiguientecódigo.
<p>
<img src="{{urlImagen}}">
</p>
<p>
<img [src]="urlImagen">
</p>
Enelprimercasoseestárealizandointerpolación,colocandocomovalordeunapropiedadalgoqueviene
deunavariabledelcomponente.Enelsegundocasoseestáusandobindingalapropiedadsrc,colocandoel
valordelamismavariable.
AmboscasosresuelvenelHTMLdelcomponenteconelmismoresultado.¿Cuáleselcorrecto?
Tenemosmásejemplos.Observaahoraesteotrocaso,enelquebásicamentecolocamosunaclaseobtenida
pormediodeunapropiedaddelcomponente.Elresultadoseráelmismo.
<ul>
<li [class]="valorClass">item 1</li>
<li class="{{valorClass}}">item 2</li>
</ul>
Porúltimoveamosuncasodondetambiénobtenemoselmismoresultado,perousandodos
aproximacionesmuchomásdiferentes.
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 84 de 113
<p>{{texto}}</p>
<p [innerHTML]="texto"></p>
Enelprimerpárrafoestamoscolocandocomocontenidountextoporinterpolación.Mientrasqueenel
segundopárrafosecolocaelmismotexto,atravésdelapropiedaddelcomponenteinnerHTML.
Siestásconfusoconambasposibilidadesseríamásquenormal.Intentaremosarrojaralgodeluzsobrecuál
deellasteconvieneusarencadacaso.
Usodelainterpolaciónconcadenas
Entodosloscasosanterioresestamosendefinitivavolcandocadenasendiversospuntosdeltemplate.
Aunqueesascadenasavecessecoloquenenpropiedadesdelcomponente,nodejandesercadenas.
Entodosloslugaresdondesetratedecolocarcadenasenunavista,puedequetengamássentidousar
interpolación,debidoenmiopiniónalaclaridaddelcódigodelavista.
Peroojo,porqueestoesunaopiniónpersonal,quenoatiendeaningúnmotivorelacionadoconelpropio
framework.Dehecho,lociertoesquenoexisteunadiferenciarealentreunauotraposibilidad,porloque
sepuedenusarindistintamente.
Loimportanteseríaestablecerunanormaaseguirportodoslosdesarrolladoresencuantoacuálusarenlos
casosenlosquenoexistadiferencia,demodoquetodoelmundotomelasmismasdecisionesy
obtengamosuncódigomáshomogéneo.
Usodepropertybindingconvaloresdistintosdecadenas
Elcasodevaloresquenoseancadenasdecaracteresesyadistinto.Realmentelainterpolacióndestrings
siempredebedevolverunacadena,porloquenoseráadecuadasiaquelloquesetienequeusarenuna
propiedadnoesdirectamenteunacadena.
Porejemplo,lapropiedad"disabled"deunbotóndebeigualarseporpropertybindingaunvalorboleano,
luegonoseráadecuadousarinterpolación.Portanto,locorrectoseríaesto:
<button [disabled]="activo">Clic aquí</button>
Enestecasoconcreto,nodeberíamosusarinterpolación,yaqueelresultadonoseráeldeseado.Por
ejemplo,estonoseríacorrecto.
<button disabled="{{activo}}">Clic aquí</button>
Elmotivoesqueactivoseinterpolaríaporlapalabra"false".Enestecasodisabled="false"enHTMLsería
lomismoquecolocarelatributo"disabled"sinacompañarlodeningúnvalor,loqueequivalealfinalaque
elbotónestédesactivado.
Endefinitiva,cadavezquetengamosqueusarundatoquenoseaunacadena,espreferiblecolocarel
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 85 de 113
bindingdepropiedad.Porejemplo,ladirectivangStyleesperaunobjetocomovalor,porloqueestaríamos
obligadosausarpropertybinding.
<div [ngStyle]="estilo">Test de estilo</div>
SanitizacióndecadenasentemplatesdeAngular
Enelcasoquetantopropertybindingcomostringinterpolationseusenparavolcarcadenaseneltemplate,
hayunadiferenciadestacableenlamaneracomolascadenassevanasanitizarantesdevolcarsealtemplate.
Envistadeestapropiedadenelcomponente:
cadenaXSS = 'Esto es un <script>alert("test")</script> con XSS';
LapropiedadcadenaXSSpresentaunproblemadeseguridad,porunainyeccióndecódigodeunscript,lo
queseconoceporXSS.
Podríamosvolcarlaenuntemplatedelasiguientemanera:
<div>{{ cadenaXSS }}</div>
<div [innerHTML]="cadenaXSS"></div>
Angularenamboscasoshaceunsaneamientodelacadena,desactivandolaetiquetaSCRIPT,paraevitar
problemasdeseguridadporinyeccióndecódigoXSS.Peroelresultadodeesesaneamientoesdiferenteen
cadacaso.
Enestecasoconcreto,lasalidaqueobtendremoseslasiguiente:
Esto es un <script>alert("test")</script> con XSSEsto es un alert("test") con XSS
Tienesqueobservarque,enelcasodelainterpolacióndestrings,laetiquetascriptteaparececomotextoen
lapágina.Esdecir,seráunsimpletextoynounaaperturaycierredeunaetiquetaparacolocarunscript
Javascript.
Esperamosqueconestasindicacioneshayasresueltoalgunasdudastípicasquepuedensurgircuando
empiezasatrabajareneldesarrolloconAngular.Ahoraestásencondicionesdeescogerlamejoropciónen
cadacaso,entrestringinterpolationyPropertybinding.
EsteartículoesobradeMiguelAngelAlvarez
Fuepublicadoporprimeravezen23/11/2017
Disponibleonlineenhttp://desarrolloweb.com/articulos/binding-propiedad-vs-interpolacion-strings.html
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 86 de 113
ServiciosenAngular
Comenzamosunaseriedeartículosquenosexplicaránquésonlosservicios,unadelaspiezasprincipalesde
lasaplicacionesenAngular.Estudiaremoscómousarserviciosdentrodeaplicaciones,cómocrearlos,cómo
agregarlosamódulosocomponentes,cómoinstanciarservicios,etc.Veremostambiénquépapeljueganlos
serviciosdentrodelmarcodeunaaplicación,conejemplosdeusoquepuedanilustrarlasbuenasprácticasa
losprogramadores.
ServiciosenAngular
QuésonlosserviciosenelframeworkJavascriptAngular,cómocrearnuestrosprimerosservices,
cómousarlosdesdeloscomponentes.
HastaahoraenelManualdeAngularhemoshabladomuchodecomponentes,ytambiéndemódulos.Pero
existenotrostiposdeartefactosquepodemosusarparaorganizarelcódigodenuestrasaplicacionesdeuna
maneramáslógicayfácildemantener.
Enimportanciaacomponentesymóduloslesiguenlosservicios.Conesteartículoiniciamossu
descripción.Losservicios,o"services"siloprefiereseninglés,sonunadelaspiezasfundamentalesenel
desarrollodeaplicacionesAngular.Veremosquéesunservicioycómodarnuestrosprimerospasosensu
creaciónyutilizaciónenunproyecto.
ConceptodeservicioenAngular
SieresyaviejoconocidodeldesarrolloconAngularsabrásloqueesunservicio,puesesunaparte
importantedentrodelaarquitecturadelasaplicacionesconesteframework.Perosieresnuevoseguroque
tevendrábientenerunapequeñadescripcióndeloqueesunservicio.
BásicamentehemosdichoanteriormentequeelprotagonistaenlasaplicacionesdeAngularesel
componente,quelasaplicacionessedesarrollanenbaseaunárboldecomponentes.Sinembargo,amedida
quenuestrosobjetivosseanmásymáscomplejos,lonormalesqueelcódigodeloscomponentestambién
vayaaumentando,implementandomuchalógicadelmodelodenegocio.
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 87 de 113
Enprincipioestonoseríatanproblemático,perosabemosquelaorganizacióndelcódigo,manteniendo
piezaspequeñasderesponsabilidadreducida,essiempremuypositiva.Además,siemprellegaráelmomento
enelquedosomáscomponentestenganqueaccederalosmismosdatosyhaceroperacionessimilarescon
ellos,quepodríanobligarnosarepetircódigo.Parasolucionarestassituacionestenemosalosservicios.
Básicamenteunservicioesunproveedordedatos,quemantienelógicadeaccesoaellosyoperativa
relacionadaconelnegocioylascosasquesehacenconlosdatosdentrodeunaaplicación.Losservicios
seránconsumidosporloscomponentes,quedelegaránenelloslaresponsabilidaddeaccederala
informaciónylarealizacióndeoperacionesconlosdatos.
Cómocrearunservicio
TalcomovienesiendocostumbreeneldesarrolloconAngular,nosapoyaremosenAngularCLIparala
creacióndelesqueleto,oscaffolding,deunservicio.
Paracrearunserviciousamoselcomando"generateservice",indicandoacontinuaciónelnombredel
servicioquequeremosgenerar.
ng generate service clientes
Estonosgeneraríaelserviciollamado"ClientesService".Lacoletilla"Service",alfinaldelnombre,tela
agregaAngularCLI,asícomotambiénnombraalarchivogeneradoconlafinalización"-service",paradejar
bienclaroqueesunservicio.
Eshabitualquequierascolocarelserviciodentrodeunmóduloenconcreto,paraloquepuedesindicarel
nombredelmódulo,unabarra"/"yelnombredelservicio.Peroatención:ahoralodetallaremosmejor,
peroqueremosadvertiryaqueestonoagregaráelservicioalcódigodeunmóduloconcreto,sinoque
colocaráelarchivoeneldirectoriodeesemódulo.Enseguidaveremosquétienesquehacerparaqueeste
servicioseasignerealmentealmóduloquedesees.
ng generate service facturacion/clientes
Nota:comolosserviciossonalgoquesesueleusardesdevarioscomponentes,muchosdesarrolladores
optanporcrearlosdentrodeunmódulocompartido,quepuedellamarse"común","shared"oalgo
parecido.
Ahora,siquieres,puedesecharleunvistazoalcódigobásicodeunservice,generadoporelCLI.Enseguida
loexaminamos.Noobstante,antesqueremosexplicarotropasoimportanteparaqueelserviciosepueda
usardentrodelaaplicación.
Agregarladeclaracióndelservicioaunmódulo
Parapoderusaresteservicioesnecesarioqueloagreguesaunmódulo.Inmediatamentelopodrásusaren
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 88 de 113
cualquieradeloscomponentesquepertenecenaestemódulo.Estepasoesimportantequelohagas,puesto
que,alcontrariodeloqueocurríaalcrearuncomponenteconelCLI,lacreacióndeunservicionoincluye
lamodificacióndelmódulodondelohascreado.
Asípues,vamosatenerquedeclararelserviciomanualmenteenelmódulo.Loharemosgraciasal
decoradordelmódulo(@NgModule),enelarrayde"providers".Eldecoradordeunmóduloconelarray
deproviderspodríaquedarmásomenosasí.
@NgModule({
imports: [
CommonModule
],
declarations: [ListadoClientesComponent],
providers: [ClientesService]
})
Obviamente,tendrásquehacerelcorrespondienteimportalmódulo,paraqueseconozcalaclase
ClientesService.
import { ClientesService } from './clientes.service';
Comodecimos,ahoraestemódulohadeclaradoelserviciocomo"provider",porloquesuscomponentes
podránusaresteservicio.
Nota:Elproviderqueacabamosdedeclararenelmóduloesunarrayquetambiénpodremosdeclarar
enuncomponente,conloquepodríamosasignarunservicioauncomponenteenconcretoynoaun
módulocompleto.Másadelanteexplicaremosdóndepuedesdeclararelprovider,dependiendodecómo
quieresquetuserviciosegestioneaniveldeaplicación.
CódigobásicodeunserviceenAngular
AhorapodemosexaminarelcódigogeneradoparanuestroservicioyaprendernuevascosasdeAngular.
Esteseríanuestroreciéncreadoservicio"ClientesService".
import { Injectable } from '@angular/core';
@Injectable()
export class ClientesService {
constructor() { }
}
Comoverás,elservicionotienenadatodavía,solosudeclaración,perohaycosasinteresantesquetenemos
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 89 de 113
queexplicar,principalmenteunnuevodecoradorquenohabíamosconocidohastaelmomento:
"@injectable".
Eldecorador@injectableindicaaAngularquelaclasequesedecora,enestecasolaclaseClientesService,
puedenecesitardependenciasquepuedanserentregadasporinyeccióndedepdendencias.Demomento
puedesquedartequelosserviciosnecesitandeestedecorador,aunquerealmentedisponerdeélnoes
condiciónindispensable.
Nota:Lainyeccióndedependenciasesunpatróndedesarrollobastantehabitualenelmundodelos
frameworks.YaesfamiliarparalosantiguosdesarrolladoresdeAngular,puesestabayaimplementada
enlasversionesdeAngularJS(1.x).Sinembargo,noesalgopropiooespecíficodeAngular,sinodela
programaciónengeneral.Tenemosunartículoqueexplicademanerateóricamáscosasimportantes
sobreestepatróndediseñodesofware:Inyeccióndedependencias.
Elimport,arribadeltodo,{Injectable}from'@angular/core',loquehaceesquenuestraclaseconozcay
seacapazdeusareldecorador@injectable.
Porlodemás,elservicioestávacío,perolepodemosponeryaalgodecódigoparaquenossirvadealgo.De
momentovamosaexponermedianteelserviciounasimplepropiedadconundato,queluegovamosa
poderconsumirdesdealgúncomponente.Paraellousamoslaspropiedadesdelaclase,talcomonos
permiteTypeScript.
export class ClientesService {
accesoFacturacion = 'https://login.example.com';
constructor() { }
}
EnnuestraclaseClientesServicehemoscreadounapropiedadllamada"accesoFacturacion",enlaque
hemosasignadounvalorqueseríacomúnparatodoslosclientes.Eldatoeslodemenos,lointeresantees
verqueladeclaraciónnodistadeotrasdeclaracionesenclasesquehayamosvistoya.
Cómoinyectardependenciasdeservicios
AhoranostocaverlamagiadeAngularysuinyeccióndedependencias,quevamosausarparapoder
disponerdelservicioenuncomponente.
Comoenotrosframeworks,enAngularlainyeccióndedependenciasserealizapormediodelconstructor.
Enelconstructordeuncomponente,quehastaahorahabíamosdejadosiemprevacío,podemosdeclarar
cualquieradelosserviciosquevamosausaryelframeworkseencargarádeproporcionarlo,sinque
tengamosquerealizarnosotrosningúntrabajoadicional.
Estoestansencillocomodeclararcomoparámetroladependenciaenelconstructordelcomponente.
constructor(private clientesService: ClientesService) { }
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 90 de 113
DeestamaneraestamosindicandoaTypeScriptyAngularquevamosausarunobjeto"clientesService"que
esdelaclase"ClientesService".Apartirdeentonces,dentrodelcomponenteexistiráeseobjeto,
proporcionandotodoslosdatosyfuncionalidaddefinidaenelservicio.
Nota:Esmuyimportantequealdeclararlainyeccióndedependenciasenelconstructornoteolvides
deladeclaracióndevisibilidad(yaseapublicoprivate),puessinolacolocasnosegenerarálapropiedad
enelobjetoconstruido.Sidefineslapropiedaddelaclasecomopública,afectaráasuvisibilidad:
constructor(publicclientesService:ClientesService)estoesalgoqueteproporcionaTypeScript.Público
oprivadoelefectoseráelmismo,secrearálapropiedad"clientesService",inyectandocomovalorun
objetodelaclaseClientesService.
Explicandocondetalleladeclaracióndepropiedadesimplícitaenelconstructor
Aquítenemosquedetenernosparaexplicaralgodelamagia,oazúcarsintáctico,queteofreceTypeScript.
Porqueelhechoquesedeclareunapropiedadenunobjetosoloporqueserecibaunparámetroenel
constructornoesalgousualenJavascript.
CuandoTypeScriptdetectaelmodificadordevisibilidad"public"o"private"enelparámetroenviadoal
constructor,inmediatamentedeclaraunapropiedadenlaclaseyleasignaelvalorrecibidoenelconstructor.
Portanto,estadeclaración:
export class ListadoClientesComponent {
constructor(public clientesService: ClientesService) { }
}
Seríaequivalenteaescribirtodoelcódigosiguiente:
export class ListadoClientesComponent {
clientesService: ClientesService;
constructor(clientesService: ClientesService) {
this.clientesService = clientesService;
}
}
Enresumen,TypeScriptentiendeque,sidefineslavisibilidaddeunparámetroenelconstructor,oque
quiereshacerenrealidadescrearunapropiedadenelobjetoreciénconstruido,conelvalorrecibidopor
parámetro.
Usandoelservicioenelcomponente
Ahora,paraacabarestaintroducciónalosserviciosenAngular,tenemosquevercómousaríamoseste
servicioenelcomponente.Nonosvamosadetenerdemasidoenhacerejemploselaborados,quepodemos
abordarmásadelante,soloveremosunpardemuestrassobrecómousarlapropiedaddeclaradaenel
servicio.
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 91 de 113
1.-Usandoelserviciodentrodelaclasedelcomponente
Dentrodelaclasedenuestrocomponente,tendremoselservicioapartirdelapropiedadusadaensu
declaración.Enelconstructordijimosqueelserviciosellamaba"clientesService",conlaprimeraen
minúsculaporserunobjeto.
Puescomocualquierotrapropiedad,accederemosaellamediantelavariable"this".
export class ListadoClientesComponent implements OnInit {
constructor(public clientesService: ClientesService) { }
ngOnInit() {
console.log(this.clientesService);
}
}
Elejemplonovaleparamucho,soloparamostrarque,desdequeestécreadoelobjetopodemosaccederal
serviciocon"this.clientesService".
Tambiénnossirvepararecordarque,elprimersitiodondepodríamosusarlosserviciosdeclaradosesenel
métodongOnInit().Dichodeotromodo,sinecesitamosdeestosserviciosparainicializarpropiedadadesen
elcomponente,ellugardondeponerlosenmarchaseríaelngOnInit().
2.-Usandoelservicioeneltemplatedeuncomponente
Porsuparte,eneltemplatedeuncomponente,podrástambiénaccederalservicio,paramostrarsus
propiedadesoinclusoinvocarsusmétodoscomorespuestaaunevento,porejemplo.
Comoelservicioestáenunapropiedaddelcomponente,podremosaccederaélmeditanteesenombrede
propiedad.
<p>
URL De acceso: {{clientesService.accesoFacturacion}}
</p>
ConclusiónalaintroducciónalosserviciosenAngular
EsoestodoloquetienesquesaberparacomenzaraexperimentarconlosserviciosenAngular.Es
momentoquepongaslasmanosenelcódigoycomiencesaexperimentarportucuenta,creandotus
propiosserviciosyusándolosdesdetuscomponentes.
Enartículosposterioresveremosserviciosunpocomáscompletos,quehaganmáscosasqueelquehemos
vistoenlapresenteentrega.
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 92 de 113
EsteartículoesobradeMiguelAngelAlvarez
Fuepublicadoporprimeravezen04/12/2017
Disponibleonlineenhttp://desarrolloweb.com/articulos/servicios-angular.html
UsarclaseseInterfacesenlosserviciosAngular
AldesarrollarserviciosconAngularesunabuenaideausarclaseseInterfacesparadefinirlas
estructurasdedatos.Veremoscómoyporqué.
SialgocaracterizaaTypeScript,ellenguajeconelquesedesarrollaenAngular,eselusodetipos.Podemos
usartiposprimitivosenvariables,loquenosayudaráarecibirayudasenelmomentoenelque
desarrollamoselcódigo,perotambiénpodemosdefinirtiposmáscomplejospormediodeclasese
interfaces.
AlolargodelManualdeAngularhemosdeclaradovariablesindicandosustiposenmuchasocasiones,pero
hastaahoranohemosusadocasinuncalasclasesparatiparymuchomenoslasinterfaces.Enlosservicios
esunbuenlugarparaempezaraacostumbrarnosaello,loquenosreportarámuchosbeneficiosalahorade
programar.
EsteartículonoavanzarátantoenloqueesofrecernuevosconocimientosdeAngular,sinomásbienenel
usodecostumbresquenosayudaráneneldíaadíayqueportantosonmuycomunesalahorade
desarrollaraplicacionesprofesionales.Paraentenderloesbuenoqueconozcaslosfundamentosde
TypeScriptytambiénespecíficamentedelasinterfacesTypeScript.Obviamente,necesitarástambiénsaber
loqueesunservicioycómocrearlosyusarlosenAngular.
Ayudasentiempodedesarrollo,noentiempodeejecución
Aunquepuederesultardecajónparamuchaspersonas,queremoscomenzarporseñalarquelasayudasque
teofreceTypeScriptseránsiempreentiempodedesarrollo.Parapoderaprovechartedeellasloideales
disponerdeuneditorqueentiendaTypeScript,mostrandoenelmomentoquedesarrollaslosproblemas
detectadosenelcódigo.
Alahoradecompilarlaaplicación,parasuejecuciónenelnavegador,tambiénteayudaráTypeScript,
especificandoloserroresquehaencontradoenelcódigo,derivadosporunusoincorrectodelasvariablesy
sustipos.
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 93 de 113
Sinembargo,unavezqueelnavegadorejecutaelcódigodebesentenderquetodoloqueinterpretaes
Javascript,porloquelostiposnointerferiránennada.Noserámáspesadoparaelnavegador,nitealertará
deproblemasquesepuedanproducir,yaqueéstesoloejecutarácódigoJavascript.Sinembargo,lociertoes
quesitipastecorrectamentetodoloqueestuvoentumanoyelcompiladornotealertódeningúnerror,
difícilmenteseproduciráunerrorporuntipomalusadoentiempodeejecución.
SiyatienesciertaexperienciaconTypeScripthabrásobservadolacantidaddeerroresquesedetectan
prematuramenteenelcódigoylomuchoqueelcompiladorteayudaamedidaqueestásescribiendo.Esto
facilitaahorrarmuchotiempoydisfrutardeunaexperienciadeprogramaciónmásagradable.Portodoello,
usarlostipossiemprequepuedasesunaideaestupendayenesteartículoqueremosexplicartecómoirun
pocomásallá,enelmarcodelosserviciosdeAngular.
Crearunaclaseparadefinireltipodetusobjetos
Lamaneramáscomúndedefinirtipos,paralaspersonasacostumbradasalenguajesdeprogramación
orientadosaobjetos,sonlasclases.
Sitienesentuaplicaciónquetrabajarconcualquiertipodeentidad,esunabuenaideaquecreesunaclase
queespecifiquequédatoscontieneesaestructura.
Sinuestraaplicaciónusaclientes,lomásnormalesquedefinaslaclasecliente,másomenoscomoesto:
class Cliente {
nombre: String;
cif: String;
direccion: String;
creado: Date;
}
Luego,cuandoquierascrearunclientepodrásdeclararlousandoeltipodelaclaseCliente.
let cliente: Cliente;
Apartirdeahora,enelcasoqueusesuncódigoquenorespeteesadeclaraciónsealertará
convenientemente.
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 94 de 113
Crearunainterfazparadefinireltipodetusobjetos
MásomenoslomismopodemosconseguirconunainterfazdeTypeScript.Esalgoqueyahemosexplicado
enelartículodeInterfacesTypeScript.Peroenresumen,puedesdefinirunainterfazdeclientesdeesta
manera.
interface Cliente {
nombre: String;
cif: String;
direccion: String;
creado: Date;
}
Luegopodemoscrearunavariableasignandolainterfacecomosifuerauntipo.
let cliente: Cliente;
Apartirdeaquíeleditornosavisarácuandoelvalorasignadonocumplalainterfaz.
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 95 de 113
¿Clasesointerfaces?
Siambasconstruccionestesirvenparamásomenoslomismo¿cuándousarclasesycuándousarinterfaces?
larespuestadependeunpocosobrecómovayasagenerarlosdatos.
Esmuyhabitualusarsimplementeinterfaces,desprovistasdeinicializaciónyfuncionalidad,yaqueesas
partesescomúnqueseandelegadasenlosservicios.Peroenelcasodeusarclases,tusnuevosobjetosserán
creadosconlapalabra"new".
let cliente1 = new Cliente();
cliente.nombre = 'EscuelaIT S.L.";
cliente.cif = 'B123';
cliente.direccion = 'C/ Del Desarrollo Web .com';
cliente.creado = new Date(Date.now());
Silosobjetosquedebescrearpresentantareasdeinicializaciónpesadas,usandoclases,podrásapoyarteen
losconstructorespararesumirlospasosparasucreación.Enestecasopodemosconseguiruncódigomás
compacto:
let cliente1 = new Cliente('EscuelaIT S.L.', 'B123', 'C/ Del Desarrollo Web .com');
Nota:obviamente,paraqueestofuncionetienesquehabercreadoelcorrespondienteconstructorenla
implementacióndelaclaseCliente.Observaqueencasodetenerunconstructorpodríamosahorrarnos
pasarleelobjetodelaclaseDate,paraasignarenlapropiedad"creado",puestoquepodríamosdelegar
enelconstructorlatareadeinstanciarunobjetoDateconlafechaconelinstanteactual.
Sinembargo,losobjetosquecontienendatospararepresentarentuaplicaciónnosiempresegeneran
mediantetupropiocódigofrontend,yaqueeshabitualqueesosdatosprovengandealgúnwebservice(API
RESTosimilar)quetelosproporcionepormediodellamadas"HTTP"(Ajax).Enestoscasosnoharás
"new",sinoqueusarásAngularparasolicitaralservidorundato,queserádevueltoenformadeunobjeto
JSONhabitualmente.Enestoscasosesespecialmenteidóneodefinirunainterfazydeclararlaelobjetoque
tedevuelvaelservidorconeltipodefinidoporesainterfaz.Másadelanteveremosejemplosdeestecasoen
concreto.
Usesonoservicioswebparatraertelosdatos,coninterfacestambiénpuedescrearobjetosque
correspondanconeltipodedatosdefinidoenlainterfaz.Simplementeloscrearíasentusserviciospor
mediodeliteralesdeobjeto.
let cliente: Cliente;
cliente = {
nombre: 'EscuelaIT',
cif: 'ESB123',
direccion: 'C/ de arriba, 1',
creado: new Date(Date.now())
};
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 96 de 113
Comopuedesver,ladecisiónsobreusarclasesointerfacespuededependerdelasnecesidadesdetu
aplicación,oinclusodetuspreferenciasocostumbresdecodificación.
Incluso,nadateimpidetenerambascosas,unainterfazyunaclaseimplementandoesainterfaz,para
disponertambiéndelaposibilidaddeinstanciarobjetosayudadosporunconstructor.
export interface ClienteInterface {
nombre: String;
cif: String;
direccion: String;
creado: Date;
}
export class Cliente implements ClienteInterface {
creado: Date;
constructor(public nombre: string, public cif: String, public direccion: String) {
this.creado = new Date(Date.now());
}
}
Definirelmodelodedatosenunarchivoexterno
Paraordenarelcódigodenuestraaplicaciónestambiénhabitualqueelmodelodedatossedefinaenun
archivoTypeScriptaparte.Enesearchivopuedesguardarladeclaracióndeltipoyluegoimportarloen
cualquierlugardondequierasusaresetipodedatos.
Archivo"clientes.modelo.ts"
Porejemplo,tendríamoselarchivo"clientes.modelo.ts"yesearchivotendría,porejemploladeclaraciónde
lainterfaz:
export interface Cliente {
nombre: String;
cif: String;
direccion: String;
creado: Date;
}
Nota:noteolvidesdecolocarlapalabra"export"delantedelnombredelainterfaz,paraqueesa
declaraciónsepuedaimportardesdeotrosarchivos.
Archivo"clientes.service.ts"
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 97 de 113
Porsuparte,enelserviciotendríamosquehacerelimportdeestetipo,definidoenclientes.modelo.ts,y
usarloaldeclararobjetos.
import { Cliente } from './cliente.modelo';
Porsupuesto,unavezdefinidoestetipodedatos,graciasalacorrespondienteinterfazimportada,lodebes
deusarentuservicio,enelmayornúmerodelugaresdondepuedas,loqueteproporcionaráuncódigomás
robusto,capazdeadvertirtedecualquiertipodeproblemasentiempodedesarrolloyahorrartemuchas
complicaciones.
Esteseríaelcódigodenuestroservicio,dondehacemosusodeltipoClienteimportado.
import { Injectable } from '@angular/core';
import { Cliente } from './cliente.modelo';
@Injectable()
export class ClientesService {
clientes: Cliente[] = [];
constructor() { }
anadirCliente(cliente: Cliente) {
this.clientes.push(cliente);
}
clienteNuevo(): Cliente {
return {
nombre: 'DesarrolloWeb.com',
cif: 'B123',
direccion: 'Oficinas de EscuelaIT, C/ Formación online nº 1',
creado: new Date(Date.now())
};
}
}
EnelcódigoanteriordebesfijarteenvariascosassobreTypeScript:
Ladeclaracióndelarray"clientes"indicaquesuselementossondetipoCliente.
Enelparámetrodelmétodo"anadirCliente"hemosdeclaradoeltipodedatosquerecibimos,de
tipoCliente.
ElvalorderetornodelmétodoclienteNuevo()sehadeclaradoqueserádetipoCliente.
Obviamente,sidurantelaescrituradetucódigo,nosoloenesteserviciosinotambiénencualquierotro
lugardondeseuse,noenvíasobjetosdelostiposesperados,TypeScriptsequejaráyteloharásaber.
Fíjateenlasiguienteimagen.Eselcódigodeuncomponentellamado"AltaClienteComponent".Hemos
cometidolaimprudenciadedeclararunclientecomodetipoString(flecharoja).Porello,todoslos
métodosenlosquetrabajamosconesecliente,apoyándonosenelservicioClientesService,estánmarcados
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 98 de 113
comosifueranunerror(flechasamarillas).
Nota:LaanteriorimagenpertenecealeditorVisualStudioCode,queyaincorporadecasatodolo
necesarioparaayudartealprogramarconTypeScript,mostrandoloscorrespondienteserrores
encontradosentiempodedesarrollo.
Conclusión
Conestohemosllegadoaunejemplodeunserviciounpocomáscomplejodelquevimosenelartículo
anterior,quetambiénsecomportarádeunmodomásrobusto,alertandodeposiblesproblemasalahorade
escribirelcódigo,ycuandoelcompiladordeTypeScriptanaliceelcódigoparaconvertirloaJavascript.
TambiénnoshadadopieausaralgunasdelascosasquenosaportaTypeScript,paraseguiraprendiendo
estesupersetdeJavascript.Esperoqueapartirdeahorapuedasesforzarteporsacarmayorpartidoaeste
lenguaje.
EsteartículoesobradeMiguelAngelAlvarez
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 99 de 113
Fuepublicadoporprimeravezen14/12/2017
Disponibleonlineenhttp://desarrolloweb.com/articulos/clases-interfaces-servicios-angular.html
PrácticaAngularconMódulos,ComponentesyServicios
VamosacrearunejemploprácticoconlovistohastaelmomentoenelManualdeAngularenel
quepondremosenusolosconocimientosadquiridossobremódulos,componentesyservicios.
SomosconscientesdequeloquehemosvistohastaestepuntodelManualdeAngular2puederesultar
complicadodeasimilarsinorealizamosunejemplocompleto,quenosayudeaverdemaneraglobalelflujo
dedesarrolloconesteframework.Porello,vamosapararnosaquíparapracticarunpoco.
VeremoscómotrabajareneldesarrollodeunaaplicaciónAngularenlaqueparticipantodoslosintegrantes
quehemosexplicadohastaahora,esdecir:módulos,componentesyservicios.
Enelpresenteejerciciovamosaconstruirunsistemadealtadeclientesyunlistadodeclientesqueirá
incrementandoítems,amedidaquelosdemosdealta.Seráinteresanteparaloslectores,peronodejadeser
unsencillodemodecómotrabajarenAngularenestosprimerospasos,pueshaymuchomásenel
frameworkquenohemostenidotiempodeaprendertodavía.
Asíquevamosaponermanosalaobra.Procurarésermuyespecífico,yendopasoapaso.Confíono
olvidarmedemencionarningunapartedelproceso.Tenencuentaademásquesolamenteresumiréalgunos
detallesdelcódigo,puesenartículospasadosdelpresentemanualhaquedadoyaexplicadotodoloque
vamosaver.
Iremospresentandolistadosdecadaunadelaspartesdelcódigoqueseiránrealizandoyalfinaldeeste
artítuloencontrarástambiénelenlacealrepositorioconelcódigocompleto.
Creamosnuestraaplicación
Elprimerpasoes,usandoelCLI,crearnuestraaplicaciónnueva.Lohacesentrandoenlacarpetadetus
proyectosyejecutandoelcomando.
ng new clientes-app
Luegopuedesentrarenlacarpetadelaaplicaciónylanzarelservidorwebdedesarrollo,paraverloquese
haconstruidohastaelmomento.
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 100 de 113
cd clientes app
ng serve -o
Creamosnuestromódulodeclientes
Laaplicaciónreciéngeneradayacontieneunmóduloprincipal,sinembargo,yoprefierodejaresemódulo
conpocasoningunacosamásdelasquenosentreganpordefectoalgenerarlaaplicaciónbásica.Porello
crearemoscomoprimerpasounmódulonuevo,llamado"ClientesModule".
EncargamosaAngularCLIlacreacióndelesqueletodenuestromóduloconelsiguientecomando:
ng generate module clientes
Definirelmodelodedatos
Vamosacomenzarnuestrocódigopordefinirlostiposdedatosquevamosausarenestaaplicación.
Vamosatrabajarconclientesygrupos.
Crearemoselmodelodedatosdentrodelacarpetadelmódulo"clientes".NoexisteenAngularun
generadordeestetipodemodelos,porloquecrearéelarchivoamanoconeleditor.Lovoyanombrar
"cliente.model.ts".
EnestearchivocolocolasinterfacesdeTypeScriptquedefinenlosdatosdemiaplicación.
export interface Cliente {
id: number;
nombre: string;
cif: string;
direccion: string;
grupo: number;
}
export interface Grupo {
id: number;
nombre: string;
}
Comoves,hecreadoeltipodedatosClientey,porcomplicarlounpoquitomás,eltipodedatosGrupo.
Así,cadaclientegeneradoperteneceráaungrupo.
Nota:Estapartedelacreacióndeinterfacesesperfectamenteopcional.Sololahacemosparausaresos
tiposenladeclaracióndevariables.ElcompiladordeTypeScriptnosavisarásienalgúnmomentono
respetamosestostiposdedatos,ayudandoentiempodedesarrolloyahorrandoalgúnqueotroerror
derivadopordespistes.
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 101 de 113
Crearunservicioparalosclientes
Loidealescrearunservicio(servicedeAngular)dondeconcentremoslastareasdetrabajoconlosdatosde
losclientes,descargandodecódigoaloscomponentesdelaaplicaciónycentralizandoenunsoloarchivola
lógicadelaaplicación.
Elserviciolovamosacreardentrodelacarpetadelmóduloclientes,porloqueespecificamoslaruta
completa.
ng generate service clientes/clientes
Enelserviciotengoquehacerelimportdelmodelodedatos,interfacesdeClienteyGrupo(creadasenel
pasoanterior).
import { Cliente, Grupo } from './cliente.model';
Nuestroservicionotienenadadelotromundo.Vamosaversucódigoyluegoexplicaremosalgúnqueotro
puntodestacable.
import { Injectable } from '@angular/core';
import { Cliente, Grupo } from './cliente.model';
@Injectable()
export class ClientesService {
private clientes: Cliente[];
private grupos: Grupo[];
constructor() {
this.grupos = [
{
id: 0,
nombre: 'Sin definir'
},
{
id: 1,
nombre: 'Activos'
},
{
id: 2,
nombre: 'Inactivos'
},
{
id: 3,
nombre: 'Deudores'
},
];
this.clientes = [];
}
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 102 de 113
getGrupos() {
return this.grupos;
}
getClientes() {
return this.clientes;
}
agregarCliente(cliente: Cliente) {
this.clientes.push(cliente);
}
nuevoCliente(): Cliente {
return {
id: this.clientes.length,
nombre: '',
cif: '',
direccion: '',
grupo: 0
};
}
}
1. Lasdospropiedadesdelserviciocontienenlosdatosquevaamantener.Sinembargo,lashemos
definidocomoprivadas,demodoquenosepuedantocardirectamenteytengamosqueusarlos
métodosdelserviciocreadosparasuacceso.
2. Losgruposlosconstruyesconunliteralenelconstructor.Generalmentelostraeríasdealgún
servicioRESToalgoparecido,perodemomentoestábienparaempezar.
3. Agregarunclienteesunsimple"push"alarraydeclientes,deunclienterecibidoporparámetro.
4. Crearunnuevoclienteessimplementedevolverunnuevoobjeto,quetienequerespetarlainterfaz,
yaqueenlafunciónnuevoCliente()seestáespecificandoqueelvalordedevoluciónseráunobjeto
deltipoCliente.
5. Fíjatequeengeneralestátodotipado,tareaopcionalperosiempreútil.
Declararelservicioparapoderusarloenloscomponentes
Unatareafundamentalparapoderusarlosserviciosesdeclararlosenel"module"dondesevayanausar.
Paraañadirelservicioenelmodule"clientes.module.ts",elprimerpasoesimportarlo.
import { ClientesService } from './clientes.service';
Luegohayquedeclararloenelarray"providers".
providers: [
ClientesService
]
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 103 de 113
Crearcomponentequedadealtaclientes
Vamosacontinuarnuestraprácticacreandounprimercomponente.Eselqueseencargarádedardealta
losclientes.
GeneramoselesqueletousandoelAngularCLI.
ng generate component clientes/altaCliente
Comenzaremoseditandoelarchivodelcomponenteyluegoiremosatrabajarconeltemplate.Portanto,
vamosaabrirelfichero"alta-cliente.component.ts".
Agregarelservicioalcomponente
Muyimportante.Parapoderusarelservicioanterior,tengoqueagregarloalcomponentereciéncreado,
realizandoelcorrespondienteimport.
import { ClientesService } from './../clientes.service';
Yposteriormenteyapodréinyectarelservicioenelconstructordelcomponente.
constructor(private clientesService: ClientesService) { }
Agregarelmodelodedatos
Parapoderseguirusandolostiposdedatosdemimodelo,vamosaagregarelarchivodondesegeneraron
lasinterfaces.
import { Cliente, Grupo } from './../cliente.model';
CódigoTypeScriptcompletodelcomponente
Elcódigocompletode"alta-cliente.component.ts",paraladefinicióndemicomponente,quedaríamáso
menosasí
import { Cliente, Grupo } from './../cliente.model';
import { ClientesService } from './../clientes.service';
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-alta-cliente',
templateUrl: './alta-cliente.component.html',
styleUrls: ['./alta-cliente.component.css']
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 104 de 113
})
export class AltaClienteComponent implements OnInit {
cliente: Cliente;
grupos: Grupo[];
constructor(private clientesService: ClientesService) { }
ngOnInit() {
this.cliente = this.clientesService.nuevoCliente();
this.grupos = this.clientesService.getGrupos();
}
nuevoCliente(): void {
this.clientesService.agregarCliente(this.cliente);
this.cliente = this.clientesService.nuevoCliente();
}
}
Esimportantemencionarestospuntos.
1. Elcomponentedeclaraunpardepropiedades,elclienteyelarraydegrupos.
2. Enelconstructor,queseejecutaloprimero,conseguimosunainstanciadelserviciodeclientes,
mediantelainyeccióndedependencias.
3. PosteriormenteseejecutangOnInit().Enestepuntoyaseharecibidoelserviciodeclientes,porlo
quelopuedousarparagenerarlosvaloresquenecesitoenlaspropiedadesdelcomponente.
4. ElmétodonuevoCliente()eselqueseejecutarácuando,desdeelformulariodealta,seproduzcael
envíodedatos.EnestecódigousamoselservicioclientesService,paraagregarelclienteygenerar
unclientenuevo,paraqueelusuariopuedaseguirdandodealtaclientessinmachacarlosclientes
anteriormentecreados.
Templatedelcomponente,conelformulariodealtadecliente
VamosaverahoracuáleselHTMLdelcomponentedealtadeclientes,quebásicamentecontieneun
formulario.
PeroantesdeponernosconelHTML,vamosahacerunaimportantetarea.Consisteendeclararenel
módulodeclientesquesevaausarladirectiva"ngModel".Paraellotenemosquehacerdospasos:
Enelarchivo"clientes.module.ts"comenzamosporimportar"FormsModule".
import { FormsModule } from '@angular/forms';
Eneldecorador,indicamoselimportsdelFormsModule.
imports: [
CommonModule,
FormsModule
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 105 de 113
],
Ahoraveamoselcódigodeltemplate,enelquereconoceráselusodelapropiedad"cliente"declaradaenel
constructor,asícomoelarraydegrupos.
<h2>Alta cliente</h2>
<p>
<span>Nombre:</span>
<input type="text" [(ngModel)]="cliente.nombre">
</p>
<p>
<span>CIF:</span>
<input type="text" [(ngModel)]="cliente.cif">
</p>
<p>
<span>Dirección:</span>
<input type="text" [(ngModel)]="cliente.direccion">
</p>
<p>
<span>Grupo:</span>
<select [(ngModel)]="cliente.grupo">
<option *ngFor="let grupo of grupos" value="{{grupo.id}}">{{grupo.nombre}}</option>
</select>
</p>
<p>
<button (click)="this.nuevoCliente()">Guardar</button>
</p>
UsarelcomponenteAltacliente
Estecomponente,dealtadeclientes,loquierousardesdeelcomponenteraízdemiaplicación.Comoel
componenteraízestádeclaradoenotromódulo,necesitohacerqueconozcaalAltaClienteComponent.
Estoloconsigoendospasos:
1.-AgregaralexportsAltaClienteComponent
Enelmódulodeclientes"clientes.module.ts"agregoalexportselcomponentequequierousardesdeotros
módulos.
exports: [
AltaClienteComponent
]
2.-Importarenelmóduloraíz
Ahora,enelmóduloraíz,"app.module.ts",debesdeclararquevasausarcomponentesquevienende
clientes.module.ts.Paraellotienesquehacerelcorrespondienteimport:
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 106 de 113
import { ClientesModule } from './clientes/clientes.module';
Yluegodeclaraselmóduloenelarraydeimports:
imports: [
BrowserModule,
ClientesModule
],
Hechoslosdospasosanteriores,yapuedesusarelcomponenteeneltemplate.Paraellosimplemente
tenemosqueescribirsutag,enelarchivo"app.component.html".
<app-alta-cliente></app-alta-cliente>
Llegadoaestepunto,sitodohaidobien,deberíasveryaelcomponentedealtadeclientesfuncionandoen
tupágina.
Nota:Siseproducecualquiererror,entoncestetocarárevisarlospasosanterioresohaceruna
búsquedaconeltextodelerrorquetedevuelvalaconsoladelnavegadoroelterminal,paraverdóndete
hasequivocado.
Crearelcomponentelistado-cliente
Paraacabarnuestraprácticavamosacrearunsegundocomponentedeaplicación.Seráelcomponenteque
nosmuestreunlistadodelosclientesquesevangenerando.
Comosiempre,comenzamosconuncomandodelCLI.
ng generate component clientes/listadoClientes
Ahoraelflujodetrabajoessimilaralrealizadoparaelcomponenteanterior.Vamosdetallandoporpasos.
Creaslosimportdelservicioydelostiposdedatosdelmodelo.
import { Cliente, Grupo } from './../cliente.model';
import { ClientesService } from './../clientes.service';
Inyectaselservicioenelconstructor.
constructor(private clientesService: ClientesService) { }
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 107 de 113
Enestecomponentetendremoscomopropiedadelarraydeclientesqueelserviciovayacreando.Asípues,
declarasdichoarraydeclientes:
clientes: Cliente[];
Cuandoseinicialiceelcomponentetienesquesolicitarlosclientesalservicio.Estolohacemosenelmétodo
ngOnInit().
ngOnInit() {
this.clientes = this.clientesService.getClientes();
}
CódigocompletodelcomponenteListadoClientesComponent
PuedesveracontinuaciónelcódigoTypeScriptcompletodecómonosquedaríaestesegundocomponente.
import { Cliente, Grupo } from './../cliente.model';
import { ClientesService } from './../clientes.service';
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-listado-clientes',
templateUrl: './listado-clientes.component.html',
styleUrls: ['./listado-clientes.component.css']
})
export class ListadoClientesComponent implements OnInit {
clientes: Cliente[];
constructor(private clientesService: ClientesService) { }
ngOnInit() {
this.clientes = this.clientesService.getClientes();
}
}
Códigodelavista
Ahorapodemosvercómoseríalavista,códigoHTML,dellistadodecomponentes.
<h2>
Listado clientes
</h2>
<div *ngIf="! clientes.length">No hay clientes por el momento</div>
<div>
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 108 de 113
<article *ngFor="let cliente of clientes">
<span>{{cliente.nombre}}</span>
<span>{{cliente.cif}}</span>
<span>{{cliente.direccion}}</span>
<span>{{cliente.grupo}}</span>
</article>
</div>
Nolohemoscomentadoanteriormente,peropuedesdarleunpocodeestiloaloscomponenteseditandoel
archivodeCSS.Porejemplo,esteseríaunpocodeCSSquepodríascolocarenelfichero"listado-
clientes.component.css".
article {
display: flex;
border-bottom: 1px solid #ddd;
padding: 10px;
font-size: 0.9em;
}
span {
display: inline-block;
width: 22%;
margin-right: 2%;
}
Usarelcomponentedellistado
Parausarestecomponentedelistadodeclientes,yaqueloqueremosinvocardesdeelmóduloraíz,tienes
queampliarelexportsdelmodule"clientes.module.ts".
exports: [
AltaClienteComponent,
ListadoClientesComponent
]
Comoparaelanteriorcomponente,dealtadeclientes,yahabíamosimportadoelmódulodeclientes,no
necesitashacernadamás.Ahorayapuedesusarelusarelcomponentedirectamenteeneltemplatedel
componenteraíz"app.component.html".
<app-listado-clientes></app-listado-clientes>
Eshoradeverdenuevolaaplicaciónconstruidaydisfrutardelbuentrabajorealizado.Elaspectodela
aplicaciónquehemosrealizadodeberíasermásomenoselsiguiente:
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 109 de 113
Conclusión
Llegadoaestepunto,hemosterminadolapráctica.Tenemosunsistemadealtayvisualizacióndeclientes
dinámico,generadoenunaaplicaciónAngularcondiferentespiezasdelframework.
ElcódigocompletolopuedesverenesterepositorioenGitHub,enesteenlacequetellevaauncommit
concreto.
Sihasentendidoelprocesoyportantohaspodidoseguirlospasos,estásenelbuencamino.Yaconoceslas
principalespiezasparaeldesarrolloenAngular.Aúnquedamuchoporaprender,perolossiguientespasos
seránmássencillos.
Sitehafaltadoinformaciónparaentenderloquehemoshechoenesteartículo,tesugieroqueleascon
calmaloscorrespondientesartículosdelManualdeAngular,enlosquedetallamoscadaunadelaspiezas
usadasenestaaplicacióndedemo.
Esnormaltambiénquetesalganerroressobrelamarcha.PararesolverloselcompiladordeTypeScriptyel
propioAngularayudanbastante.Puedespreguntaro"googlear"paraencontrarrespuestasatusproblemas.
EsteartículoesobradeMiguelAngelAlvarez
Fuepublicadoporprimeravezen05/01/2018
Disponibleonlineenhttp://desarrolloweb.com/articulos/practica-angular-modulos-componentes-servicios.html
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 110 de 113
ObservablesenAngular
Enlospróximosartículosintroduciremoselconceptodeobservable,unaherramientaparalaprogramación
reactivadentrodeaplicacionesdeAngular,capazdeaumentarsensiblementeelrendimientodelas
aplicaciones.
IntroducciónteóricaalosobservablesenAngular
Aclaramosconceptossobrelosobservables,porquésonimportantesenAngular.,quéesla
programaciónreactivayquéesRxJS.
EnesteartículovamosacomenzarunanuevaetapaennuestroconocimientodeAngular,dedicandotiempo
paraunaprimeraaproximaciónalos"observables",quesonunadelasprincipalesnovedadesdel
frameworkapartirdeAngular2.Losobservablesrepresentantambiénunadelasmejoresformasde
optimizarunaaplicación,aumentandosurendimiento.
EnAngularseusanmucholosobservables,dadasuutilidadyversatilidad,aunquehemosdeadmitirqueno
esunatareasencilladeaprenderinicialmente.Intentaremosacercártelosdeunamanerasencilla,paraquelos
puedasirdigiriendopocoapocoysuavizarsucurvadeaprendizaje.Demomento,enesteartículodel
ManualdeAngular,nuestroobjetivoesofrecerunaintroduccióngeneral,paraquecomiencesaconocerlos,
asícomoelconceptodeprogramaciónreactiva.
El"porqué"delosobservables
Hemosdichoquelosobservablessonunadelasprincipalesherramientasparaprogramaraplicacionesde
mayorrendimiento.ObviamenteeseeselmotivoporelcuálseusanenAngular.Pero,¿dónderesideesa
mejoraderendimiento?
UnodelosmotivosporlosqueAngular(yenespecialsupredecesorAngularJS)seconvirtióenun
frameworktanusadoessucapacidaddeproporcionarunaactualizaciónautomáticadelasfuentesde
información.Esdecir,enAngularsomoscapacesdeusarunalmacéndedatosy,cuandosemodificaese
almacén,recibirautomáticamentesuscambios,sinquetengamosqueprogramaramanoesetránsitodela
información.
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 111 de 113
Incluso,aunqueuncomponenteseaelencargadodeactualizaresealmacéndedatos,hemosvistoque,
usandoservicios,podemosconseguirqueotroscomponentesrecibanautomáticamentelasactualizaciones.
Sinolorecuerdas,consultaelartículodeprácticaconAngularconcomponentes,módulosyservicios.
Sinembargo,aunqueAngularnosahorraescribirmuchocódigo,éstotieneuncosteentérminosde
rendimiento.QuizásunaaplicaciónpequeñanoseverátanafectadaporeltrabajoqueAngularhacepor
debajo,paraproporcionarnosautomáticamenteloscambios,perosísedejaránotarenaplicaciones
medianas.Yalasmásgrandesaplicacionesacusaránsensiblementeunamayorfaltaderendimiento.
Nota:Parasermásconcreto,Angularpordebajohaceunaseriedeoperacionesdemanerarepetitiva,en
lasqueconsultaloscambiosenlafuentededatos,parasabercuándoseactualizanyentoncesrealizarlas
accionesoportunaspararefrescarlosdatosenloslugaresdondeseestánusando.Esanoeralamejor
estrategiaposibleyporestemotivo,otraslibreríascomoReactJS,quesupieronimplementarunpatrón
decomportamientomásacertado,capazdeofrecermayorrendimiento,comenzaronaganarsuespacio
antelahegemoníadeAngular.
LasoluciónaplicadaenAngular2(yquemantienenlassiguientesversiones,4,5...)fuéusarunpatrón
llamado"Observable",quebásicamentenosahorratenerquehacerconsultasrepetitivasdeaccesoala
fuentedeinformación,aumentandoelrendimientodelasaplicaciones.
Programaciónreactiva
Hacemosaquíunapausaparaintroducirotroconceptorelacionadoconlosobservables,comoesla
"programaciónreactiva".Aunqueparahablardeprogramaciónreactivaexistenlibrosenteros,vamosa
explicarmuyporencimasobreloquesetrata.
Programacióntradicional
Primeroestablezcamosunabasesobreunconocimientodelaprogramacióntradicionalquenosparece
obvio,peroqueeslabasesobrelaprogramaciónreactiva,quetienequeverconelflujodeejecucióndelas
instrucciones.
Enprogramacióntradicionallasinstruccionesseejecutanunadetrásdeotra.Portanto,sirealizamosun
cálculocondosvariablesyobtenemosunresultado,aunquelasvariablesusadasparahacerelcálculo
cambienenelfuturo,elcálculoyaserealizóyportantoelresultadonocambiará.
let a = 1;
let b = 3;
let resultado = a + b; // resultado vale 4
// Más tarde en las instrucciones...
a = 7; // Asignamos otro valor a la variable a
// Aunque se cambie el valor de "a", resultado sigue valiendo 4,
Elanteriorcódigoilustraelmododetrabajodelaprogramacióntradicionalylaprincipaldiferenciacon
respectoalaprogramaciónreactiva.Aunquepuedaparecermagia,enprogramaciónreactivalavariable
resultadohabríaactualizadosuvaloralalterarselasvariablesconlasqueserealizóelcálculo.
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 112 de 113
Programaciónreactivaylosflujosdedatos
Parafacilitarelcambiodecomportamientoentrelaprogramacióntradicionalylaprogramaciónreactiva,en
éstaúltimaseusanintensivamentelosflujosdedatos.Laprogramaciónreactivaeslaprogramación
conflujosdedatosasíncronos.
Enprogramaciónreactivasepuedencrearflujos(streams)apartirdecualquiercosa,comopodríaserlos
valoresqueunavariabletomealolargodeltiempo.Todopuedeserunflujodedatos,comolosclicssobre
unbotón,cambiosenunaestructuradedatos,unaconsultaparatraerunJSONdelservidor,unfeedRSS,
ellistadodetuitsdelaspersonasalasquesigues,etc.
Enlaprogramaciónreactivasetienenmuyencuentaesosflujosdedatos,creandosistemasquesoncapaces
deconsumirlosdedistintosmodos,fijándoseenloquerealmentelesimportadeestosstreamsy
desechandoloqueno.Paraellosedisponedediversasherramientasquepermitenfiltrarlosstreams,
combinarlos,crearunosstreamsapartirdeotros,etc.
Comoobjetivofinal,reactiveprogramingseocupadelanzardiversostiposdeeventossobrelosflujos:
Laaparicióndealgointeresantedentrodeeseflujo
Laaparicióndeunerrorenelstream
Lafinalizacióndelstream
Comoprogramadores,mediantecódigo,podemosespecificarquéesloquedebeocurrircuandocualquiera
deesoseventosseproduzca.
Siquieresleermássobreprogramaciónreactiva,unaintroducciónmuchomásdetalladalaencuentrasenel
artículoTheintroductiontoReactiveProgrammingyou'vebeenmissing.
Observablesyprogramaciónreactiva
Elpatrónobservablenoesmásqueunmododeimplementacióndelaprogramaciónreactiva,que
básicamenteponeenfuncionamientodiversosactoresparaproducirlosefectosdeseados,queesreaccionar
anteelflujodelosdistintoseventosproducidos.Mejordicho,producirdichoseventosyconsumirlosde
diversosmodos.
Loscomponentesprincipalesdeestepatrónson:
Observable:Esaquelloquequeremosobservar,queseráimplementadomedianteunacolecciónde
eventosovaloresfuturos.Unobservablepuedesercreadoapartirdeeventosdeusuarioderivados
delusodeunformulario,unallamadaHTTP,unalmacéndedatos,etc.Medianteelobservablenos
podemossuscribiraeventosquenospermitenhacercosascuandocambialoqueseesté
observando.
Observer:Eselactorquesededicaaobservar.Básicamenteseimplementamedianteunacolección
defuncionescallbackquenospermitenescucharloseventosovaloresemitidosporunobservable.
Lascallbackspermitiránespecificarcódigoaejecutarfrenteaundatoenelflujo,unerroroelfinal
delflujo.
Subject:eselemisordeeventos,queescapazdecrearelflujodeeventoscuandoelobservable
sufrecambios.Esoseventosseránlosqueseconsumanenlosobservers.
Manual de Angular
http://desarrolloweb.com/manuales/manual-angular-2.html Página 113 de 113
Estassonlasbasesdelpatrón.Sabemosquehemospuestovariosconceptosquesóloquedaránmásclaros
cuandolosveamosencódigo.Serádentrodepoco.Aunquevistasmuyporencima,sonconceptosconlos
quemerecelapenacomenzarafamiliarizarse.
Existendiversaslibreríasparaimplementarprogramaciónreactivaquehacenusodelpatrónobservable.
UnadeellasesRxJS,queeslaqueseusaenAngular.
QuéesRxJS
ReactiveExtensions(Rx)esunalibreríahechaporMicrosoftparaimplementarlaprogramaciónreactiva,
creandoaplicacionesquesoncapacesdeusarelpatrónobservableparagestionaroperacionesasíncronas.
PorsuparteRxJSeslaimplementaciónenJavascriptdeReactiveExtensions,unamásdelasadaptaciones
existentesenmuchosotroslenguajesdeprogramación.
RxJSnosofreceunabasedecódigoJavascriptmuyinteresanteparaprogramaciónreactiva,nosolopara
produciryconsumirstreams,sinotambiénparamanipularlos.ComoesJavascriptlapuedesusaren
cualquierproyectoenestelenguaje,tantodelladodelclientecomodelladodelservidor.
LalibreríaRxJSdeporsíesmateriadeestudioparauncursoounmanual,perotenemosqueintroducirla
aquíporquelausaAngularparaimplementarsusobservables.Esdecir,envezdereinventarlarueda,
AngularseapoyaenRxJSparaimplementarlaprogramaciónreactiva,capazdemejorarsensiblementeel
desempeñodelasaplicacionesquerealicemosconesteframework.
Comohabrásentendido,podemosusarRxJSendiversoscontextosyunodeellossonlasaplicaciones
Angular.EnlospróximosartículoscomenzaremosavercódigodeAngularparalacreacióndeobservables
ydealgúnmodoestaremosaprendiendolapropialibreríaRxJS.
Conclusión
Conloquehemostratadoenesteartículotienesunabasedeconocimientoesencial,necesariaparadarel
pasodeenfrentartealosobservablesenAngular.
Nohemosvistonadadecódigoperonotepreocupes,porqueenelpróximoartículovamosarealizaruna
prácticadeusodeobservablesenAngularconlaquepodráspracticarconestemodelodetrabajoparala
comunicacióndecambios.Loimportanteporahoraesaclararconceptosyestablecerlasbasesde
conocimientonecesariasparaque,alahoradeverelcódigo,tengasunamayorfacilidaddeentendercómo
funcionaestodelosobservablesylaprogramaciónreactiva.
EsteartículoesobradeMiguelAngelAlvarez
Fuepublicadoporprimeravezen16/01/2018
Disponibleonlineenhttp://desarrolloweb.com/articulos/introduccion-teorica-observables-angular.html