Manual-Angularjs Desarrollo Web
Manual-Angularjs Desarrollo Web
http://desarrolloweb.com/manuales/manual-angularjs.html
Pgina 1 de 129
Manual de AngularJS
http://desarrolloweb.com/manuales/manual-angularjs.html
Pgina 2 de 129
Manual de AngularJS
Alberto Basalo
Alberto Basalo es experto en Angular y otras tecnologas basadas en Javascript,
como NodeJS y MongoDB. Es director de gora Binaria, empresa dedicada al
desarrollo de aplicaciones y a la formacin a travs de Academia Binaria.
Pedro Hurtado
Amante de las novedades, defensor de la comunidad. Compartir es la fuente de
la Sabiduria. No te cierres en tu mundo y da lo mismo tus creencias. Estamos en
mundo abierto. Desarrollador en .Net, Nodejs, Angular convencido y porque
no el resto, como G
Pgina 3 de 129
Manual de AngularJS
Xavier, conocido entre sus amigos como Xavi Paper, es CTO en Ambiental
Intelligence & Interaction, como desarrollador es especialista en tecnologas
Microsoft y en Javascript, impulsor del framework AngularJS.
http://desarrolloweb.com/manuales/manual-angularjs.html
Pgina 4 de 129
Manual de AngularJS
Introduccin a AngularJS
Esta es una introduccin de manera conceptual al framework Javascript AngularJS. Explicamos por qu
cada vez tiene ms importancia el desarrollo de aplicaciones web con alta carga de Javascript y por qu son
esenciales este tipo de libreras para una programacin ms sencilla, rpida y de fcil mantenimiento.
Completaremos la introduccin con una prctica en la que podremos experimentar con un primer ejemplo
en Angular.
Por qu AngularJS
Cmo los frameworks Javascript en general y AngularJS en concreto nos sirven para solucionar las
necesidades actuales de la informtica, en cuanto a desarrollo multiplataforma de aplicaciones
grandes o enormes que se asemejan a las de escritorio.
Con este artculo comenzamos una serie dedicada a AngularJS, el framework Javascript MV* que nos
permite un desarrollo rpido y potente de aplicaciones web basadas en Javascript del lado del cliente.
AngularJS es un conjunto de libreras apoyadas por Google que tiene un futuro muy prometedor y que en
estos momentos se encuentra en boca de todos. No se trata de una moda pasajera, sino de una tecnologa
que por su utilidad y caractersticas ha venido para quedarse.
A lo largo de varios artculos nos iremos introduciendo en este framework, de una manera bastante prctica.
Sin embargo vamos a comenzar con una introduccin ms terica y retrospectiva que nos haga entender el
porqu de la proliferacin de frameworks Javascript y el motivo por el que Angular es una apuesta segura
entre sus competidores.
Nota: Esta es una transcripcin libre de la charla de Alberto Basalo que nos ofreci en abierto en un
webinar de DesarrolloWeb.com / EscuelaIT. El ttulo de esta primera parte que ahora te resumimos es
"Desarrollo de aplicaciones de negocio y los retos y soluciones de 2014". Al final del artculo podrs ver
el vdeo de la charla.
http://desarrolloweb.com/manuales/manual-angularjs.html
Pgina 5 de 129
Manual de AngularJS
Un poco de historia
"El software sigue al hardware". Esta es una afirmacin que nos indica que programamos para aquellas
mquinas en las que vamos a ejecutar los programas. Puede resultar obvio, pero como ejemplo se puede
sealar que no vamos a programar para las "Google Glass" si aun no las han creado, o si aun no han
liberado el SDK. Cuando empez la informtica en los aos 60 existan ordenadores arcaicos y como
programadores estabas limitado a las posibilidades de stos.
Conforme avanz el desarrollo de la informtica aparecieron otros ordenadores. Al principio no estaban
conectados entre s ya que no existan las redes locales, ni mucho menos Internet. Como no haba redes
estabas limitado a lo que ocurra dentro de esa mquina y quizs los programadores tenan una vida ms
sencilla: estas limitaciones provocaban que no tuvieran que preocuparse por ciertas cosas. Incluso las
opciones para crear los programas -tecnologas y lenguajes- no eran demasiadas, al contrario, quizs en tu
sistema operativo estabas obligado a trabajar con un lenguaje o un par de ellos nada ms.
Luego aparecieron las redes, apareci Internet y los ordenadores comenzaron a conectarse entre s. Existen
servidores y terminales que ya no son tontos, pero estamos trabajando con lenguajes sencillos, como HTML
-al principio ni exista CSS- y ya acercndose al final del milenio aparecen lenguajes como Javascript capaces
de hacer algunas cosas sencillas.
El reto hoy
Hoy la situacin ya no es la que se describe anteriormente, sino que el panorama ha cambiado mucho.
Por un lado el abaratamiento de las comunicaciones hace que aparezcan grandes centros de proceso de
datos que nos facilitan el acceso a tecnologa de primer orden, lo que se llama la nube. Ahora cualquier
empresa, incluso las ms pequeas, tienen la posibilidad de acceder a servidores de aplicaciones.
Se ha acabado la "tirana de Windows": hoy existen varios sistemas operativos y se usan para todo tipo de
cosas. Los Mac ya no los usan solamente los diseadores, los Linux no son terreno exclusivo de los
desarrolladores, sino que cualquier persona usa esos sistemas para todo tipo de tareas. Los desarrolladores
no pueden centrarse en un nico sistema y limitar el servicio a las personas de determinada plataforma.
La cosa no queda ah, puesto que ya no solo hablamos de ordenadores de escritorio y porttiles, adems
tenemos la tecnologa mvil y los dispositivos como tablets. Yendo todava un poco ms all tenemos los
televisores inteligentes, las Google Glass y al final de todo, el "Internet of Things".
Esta es la foto actual, que es muy distinta a la de las ltimas dcadas. Tenemos la nube con sus
innumerables posibilidades y tenemos una infinita gama de ordenadores y dispositivos a los que
atender.
En qu programar?
A toda la situacin relatada anteriormente le tenemos que sumar una interminable lista de necesidades en el
campo de la informtica y, por supuesto, tecnologas y lenguajes que nos sirven para resolverlas.
Programo para la web o para el escritorio? realizo desarrollo nativo o multiplataforma? La industria te da
soluciones y aporta todo tipo de alternativas, Java, .net, Python, RoR, Objective-C y otros ms arcaicos
como Cobol, pero es inevitable plantearse cul de ellos es ms adecuado para resolver los problemas.
http://desarrolloweb.com/manuales/manual-angularjs.html
Pgina 6 de 129
Manual de AngularJS
HTML5 + JS
Si quieres realizar un desarrollo que se adapte a todo tipo de sistemas y dispositivos que puedan llegar a
aparecer, una solucin es buscar algo que sea comn a todos los sistemas y buscar algo que tengas seguridad
que lo van a entender todos.
Existe un consenso en el mundo de la tecnologa de dar soporte a HTML5 y Javascript. La situacin
actual y la industria nos hace pensar que estos lenguajes estarn disponibles en todo sistema donde circule
un bit. Por ello, podemos ver a estas tecnologas de estndares abiertos como un caballo ganador.
Eso s, HTML5 + Javascript compiten con las soluciones nativas y en trminos de rendimiento es muy
difcil que puedan llegar a equipararse. El lenguaje nativo, adems, siempre tendr mayor facildad de acceso
a las caractersticas especficas y funcionalidades del dispositivo.
Tambin compite con los lenguajes ms clsicos como C, PHP, Java donde hay ya muchsimo trabajo ya
realizado en forma de libreras disponibles para los programadores. Esta situacin est cambiando, pero hay
que observar que hasta hace poco era complicado hacer grandes programas con Javascript, pues el lenguaje
serva para bien poco. Con la llegada de HTML5 y las diversas API se ha extendido mucho y se ha hecho
mucho ms poderoso, pero todava faltaba mucho terreno para que Javascript se considerase un lenguaje
robusto, capaz de cumplir las necesidades de aplicaciones grandes.
Pgina 7 de 129
Manual de AngularJS
los frameworks nos traen un conjunto de paradigmas y patrones que facilitan el desarrollo del software y
sobre todo su mantenimiento. Nos referimos principalmente al llamado MVC, que es la separacin del
cdigo en diferentes responsabilidades. Ahora cada parte del cdigo debemos situarlo en un lugar
determinado, y ese orden nos facilita que los desarrollos sean ms manejables. Sobre todo esa mejora
permite que en un futuro puedas "meter mano" al software para mantenerlo cuando sea necesario. Todo
redunda en la calidad del cdigo, lo que es indispensable para los proyectos y los programadores.
Pgina 8 de 129
Manual de AngularJS
bindign" que te permite que los distintos componentes de tu aplicacin estn al tanto de los cambios para
modificar su estado automticamente, sin necesidad de suscribirse a eventos y realizar otro tipo de acciones
por medio de lneas de cdigo. En este sentido hay tests objetivos que nos permiten ver que la misma
aplicacin hecha con AngularJS tiene sensiblemente menos cdigo que en BackboneJS y quizs con otros
frameworks pase lo mismo.
Segundo la comunidad. AngularJS tiene el apoyo de Google y una gran comunidad detrs. Las bsquedas de
AngularJS se han disparado mientras que las de otros frameworks no han mejorado o han cado. Esto
quiere decir en definitiva que encontrars ms documentacin y ms componentes de otros desarrolladores
para basar tu trabajo en ellos.
Hasta aqu el primer artculo de AngularJS, que ha sido un tanto general. Solo esperamos que te hayas
quedado con ganas de ms. En el siguiente post te explicaremos qu es AngularJS.
A continuacin encuentras la charla que ha servido de base para escribir este artculo, de Alberto Basalo.
Muy entretenida e interesante, capaz de abrirnos la mente y motivarnos a aprender AngularJS.
Para ver este vdeo es necesario visitar el artculo original en: http://desarrolloweb.com/articulos/porque-angularjs.html
Este artculo es obra de Alberto Basalo
Fue publicado por primera vez en 21/08/2014
Disponible online en http://desarrolloweb.com/articulos/por-que-angularjs.html
Qu es AngularJS
Descripcin general sobre AngularJS, el framework Javascript, as como los principales
componentes que tiene y los conceptos que debemos conocer antes de poner manos en el cdigo.
AngularJS es Javascript. Es un proyecto de cdigo abierto, realizado en Javascript que contiene un conjunto
de libreras tiles para el desarrollo de aplicaciones web y propone una serie de patrones de diseo para
llevarlas a cabo. En pocas palabras, es lo que se conoce como un framework para el desarrollo, en esta caso
sobre el lenguaje Javascript con programacin del lado del cliente.
Puedes encontrar el proyecto de AngularJS en su propio sitio web: AngularJS, Superheroic JavaScript MVW
Framework. Al ser un proyecto de cdigo abierto cualquier persona con un poco de curiosidad echar un
vistazo con profundidad y ver cmo se ha escrito, incluso admiten colaboraciones de desarrolladores que
quiera aportar cosas.
http://desarrolloweb.com/manuales/manual-angularjs.html
Pgina 9 de 129
Manual de AngularJS
Nota: Las SPA o "Aplicaciones de una sola pgina", son sitios web donde los usuarios perciben una
experiencia similar a la que se tiene con las aplicaciones de escritorio. En este tipo de sitios la pgina no
se recarga, no existe una navegacin de una pgina a otra totalmente diferente, sino que se van
intercambiando las "vistas". Tcnicamente podramos decir que, al interactuar con el sitio, el navegador
no recarga todo el contenido, sino nicamente vistas dentro de la misma pgina.
Pgina 10 de 129
Manual de AngularJS
Controlador.
Vistas: Ser el HTML y todo lo que represente datos o informacin.
Controladores: Se encargarn de la lgica de la aplicacin y sobre todo de las llamadas "Factoras"
y "Servicios" para mover datos contra servidores o memoria local en HTML5.
Modelo de la vista: En Angular el "Modelo" es algo ms de aquello que se entiende habitualmente
cuando te hablan del MVC tradicional, osea, las vistas son algo ms que el modelo de datos. En
modo de ejemplo, en aplicaciones de negocio donde tienes que manejar la contabilidad de una
empresa, el modelo seran los movimientos contables. Pero en una pantalla concreta de tu
aplicacin es posible que tengas que ver otras cosas, adems del movimiento contable, como el
nombre de los usuarios, los permisos que tienen, si pueden ver los datos, editarlos, etc. Toda esa
informacin, que es til para el programador pero que no forma parte del modelo del negocio, es a
lo que llamamos el "Scope" que es el modelo en Angular.
Nota: Por ese motivo por el cual en AngularJS tienes unos modelos un poco diferentes, algunos autores
dicen que el patrn que utiliza el framework es el MVVM Model-View-View-Model. En resumen, el
modelo de la vista son los datos ms los datos adicionales que necesitas para mostrarlos adecuadamente.
Adems del patrn principal, descrito hasta ahora tenemos los mdulos:
Mdulos: La manera que nos va a proponer AngularJS para que nosotros como desarrolladores seamos
cada vez ms ordenados, que no tengamos excusas para no hacer un buen cdigo, para evitar el cdigo
espaguetti, ficheros gigantescos con miles de lneas de cdigo, etc. Podemos dividir las cosas, evitar el
infierno de las variables globales en Javascript, etc. Con los mdulos podemos realizar aplicaciones bien
hechas, de las que un programador pueda sentirse orgulloso y sobre todo, que nos facilite su desarrollo y el
mantenimiento.
http://desarrolloweb.com/manuales/manual-angularjs.html
Pgina 11 de 129
Manual de AngularJS
Es importante sealar aqu, aunque se volver a incidir sobre ese punto, que nunca jams se deber acceder
al DOM desde la parte del Javascript. Es un pecado mortal ya que esa parte debe ser programada de manera
agnstica, sin tener en cuenta la manera en la que se van a presentar los datos.
En medio tendremos el denominado Scope, que como decimos representa al modelo en Angular. En
resumen no es ms que un objeto Javascript el cual puedes extender creando propiedades que pueden ser
datos o funciones. Nos sirve para comunicar desde la parte del HTML a la parte del Javascript y viceversa.
Es donde se produce la "magia" en Angular y aunque esto no sea del todo cierto, a modo de explicacin
para que se entienda algo mejor, podemos decir que AngularJS se va a suscribir a los cambios que ocurran
en el scope para actualizar la vista. Y al revs, se suscribir a los cambios que ocurran en la vista y con eso
actualizar el scope.
En el siguiente artculo comenzaremos ya con cdigo, as que los impacientes tendrn ya sus deseos hechos
realidad.
Puedes ver el vdeo de esta parte de la presentacin sobre Qu es AngularJS.
Para ver este vdeo es necesario visitar el artculo original en: http://desarrolloweb.com/articulos/quees-angularjs-descripcion-framework-javascript-conceptos.html
Este artculo es obra de Alberto Basalo
Fue publicado por primera vez en 27/08/2014
Disponible online en http://desarrolloweb.com/articulos/que-es-angularjs-descripcion-framework-javascriptconceptos.html
http://desarrolloweb.com/manuales/manual-angularjs.html
Pgina 12 de 129
Manual de AngularJS
AngularJS Vs jQuery
Complementarias? Competidoras? Analizamos similitudes y diferencias de jQuery y AngularJS,
casos en los que sera ms aconsejable una u otra librera y una comparativa de cdigo, de un
mismo problema, resuelto con ambas herramientas.
No quiero comenzar a escribir sin explicar bien el ttulo de este artculo. Quien tenga alguna idea de
AngularJS quizs piense que hemos patinado al intentar enfrentarlo a jQuery pues son libreras con
filosofas diferentes, que sirven para resolver distintos tipos de problemas. En definitiva, las dos son para
endulzar el Javascript del lado del cliente, pero cada una es adecuada para un tipo de problemas. Sobre todo
esto hablaremos con bastante detalle a lo largo del artculo, para no causar confusin entre los lectores,
tanto noveles como experimentados. Unimos adems una comparativa de las filosofas de ambas
herramientas, reflejada en el cdigo de resolucin de un mismo problema, lo que nos ayudar a entender
mejor sus diferencias.
Dicho eso, aclaro que la eleccin del ttulo responde a sta es una duda habitual de las personas que se
interesan por Angular u otras libreras MV* de Javascript. Si t tienes la duda, o quieres entender mejor la
filosofa de AngularJS, puedes seguir leyendo. Si t ya conoces perfectamente las diferencias y no necesitas
saber ms, puedes saltarte este artculo y seguir tranquilamente por el siguiente del Manual de AngularJS.
Muchos de nosotros hemos entrado en el mundo de las libreras Javascript de la mano de jQuery. Incluso
hay tambin muchos desarrolladores que han entrado en el lenguaje Javascript aprendiendo jQuery. El caso
es que en el pasado lustro jQuery ha dominado el mundo del desarrollo del lado del cliente y sigue usndose
de manera muy habitual, hasta el punto de considerarse casi un estndar. Sin embargo, nuevas libreras
Javascript y frameworks como AngularJS van un paso ms all de donde se queda jQuery, aportando
muchas otras utilidades y patrones de diseo de software.
Despus de haber invertido tanto tiempo en el aprendizaje de jQuery, una de las preguntas que muchos nos
hacemos cuando conocemos AngularJS es Qu me queda de todo eso cuando me pase al desarrollo con
AngularJS? Qu pasa con jQuery? Sirven para hacer lo mismo? son competidores? complementarios?
Nota: Parte de este artculo es transcripcin de una parte de la presentacin sobre AngularJS que nos
ofreci en DesarrolloWeb.com Alberto Basalo. Adems adicionalmente hemos aadido una
comparativa entre el "Hola mundo" tpico de AngularJS con esta librera y el cdigo que deberas
emplear si usas jQuery.
http://desarrolloweb.com/manuales/manual-angularjs.html
Pgina 13 de 129
Manual de AngularJS
Nota: Para ms informacin puedes leerte los captulos iniciales del Manual de AngularJS, donde
aprenders ms sobre las caractersticas del framework.
Nota: Incluso jQuery puede traer mejoras de rendimiento con respecto a la misma funcionalidad que
viene en AngularJS. No es el caso ahora estudiar el rendimiento de una y otra librera sino entender sus
http://desarrolloweb.com/manuales/manual-angularjs.html
Pgina 14 de 129
Manual de AngularJS
diferencias. No obstante, a pesar de jQuery poder dar un poco ms de rendimiento en tiempo de
ejecucin, se notar solamente con trabajos intensivos y habra que tener en cuenta el tiempo de carga
de la librera adicional para comparar definitivamente usar Angulas a secas o Angular con jQuery.
http://desarrolloweb.com/manuales/manual-angularjs.html
Pgina 15 de 129
Manual de AngularJS
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Ej Hola Mundo desarrollado en jQuery</title>
</head>
<body>
<h1>Hola</h1>
<form>
Cmo te llamas? <input type="text" id="nombre">
</form>
<script src="https://code.jquery.com/jquery-1.11.1.min.js"></script>
<script>
$(function(){
var campoTexto = $("#nombre");
var titular = $("h1");
campoTexto.on("keyup", function(){
titular.text("Hola " + campoTexto.val());
});
});
</script>
</body>
</html>
En AngularJS ya vimos el cdigo necesario en un artculo anterior, pero lo reproducimos para poder
compararlos fcilmente.
<!DOCTYPE html>
<html lang="en" ng-app>
<head>
<meta charset="UTF-8">
<title>Ej Hola Mundo desarrollado en AngularJS</title>
</head>
<body>
<h1>Hola {{nombre}}</h1>
<form>
Cmo te llamas? <input type="text" ng-model="nombre">
</form>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
</body>
</html>
Nota: Esta comparativa la puedes ver realizada en vdeo, en ingls, aunque resulta realmente fcil de
seguirlo si entiendes un poco estos cdigos: https://www.youtube.com/watch?v=uFTFsKmkQnQ
Como habrs observado, con AngularJS se simplifica nuestra vida. No solo que no necesitas hacer muchas
de las cosas que en jQuery tienes que programar "a mano", como el acceso al campo de texto para recuperar
http://desarrolloweb.com/manuales/manual-angularjs.html
Pgina 16 de 129
Manual de AngularJS
el valor, la creacin del evento de teclado para hacer cosas cuando se escribe dentro del campo de texto, etc.
Lo que ms debera llamar nuestra atencin es que el cdigo de AngularJS es mucho ms entendible, incluso
por personas que no tengan idea de programar. Como puedes deducir, en Angular escribimos generalmente
menos cdigo Javascript, pero s es importante decir que debido al uso del patrn MV* (separacin del
cdigo por sus diferentes objetivos), en ejemplos ms avanzados observars que entran en juego diferentes
factores que complican las soluciones. Generalmente, aunque en la mtrica de lneas de cdigo AngularJS
pueda ganar a jQuery, tambin debes saber que te exigir mayor capacidad de abstraccin y entender
diversos conceptos de patrones de diseo de software.
Todo ello nos debe hacer entender mejor la potencia de AngularJS. Pero ojo, sin desmerecer a jQuery, pues
debe quedar claro que cada librera es til en su campo.
Pgina 17 de 129
Manual de AngularJS
Editor de cdigo: puede ser cualquiera que ests acostumbrado a usar, no necesitas cambiarlo para
programar con Angular. Lo que es interesante es que sea un editor para programadores, que te
permita diversas ayudas al escribir el cdigo, coloreado de sintaxis, ayudas contextuales, etc.
Notepad++, Sublime Text, Komodo Edit, Brackets, etc. Cualquiera es bueno. Si ests
acostumbrado a IDEs ms complejos como Eclipse o PhpStorm, puedes quedarte tambin con
ellos.
Navegador: Puedes usar cualquier navegador para ver un desarrollo basado en Angular.
Generalmente tendrs incluso varios navegadores para probar tu pgina en cada uno de ellos y
comprobar que todo est en orden. Solo te recomendamos tener a Google Chrome entre tu batera
de navegadores, pues luego hablaremos de una extensin que existe para ste que te permite
examinar y depurar pginas donde AngularJS est trabajando.
Descarga de AngularJS
Si quieres trabajar con AngularJS tienes que incluir el script del framework en tu pgina. Esto lo puedes
hacer de varias maneras, o bien te descargas la librera por completo y la colocas en un directorio de tu
proyecto, o bien usas un CDN para traerte la librera desde un servidor remoto. En principio es indiferente
a nivel didctico, as que nosotros vamos a comenzar del modo ms sencillo, que es utilizar el CDN.
Accedes a la pgina de AngularJS: https://angularjs.org/
Pulsas el botn de descarga y encontrars diversas opciones. Escoges la versin del framework (si es que te
lo permite) y que est minimizada (minified). Luego encontrars un campo de texto donde est la URL de la
librera (esa URL est marcada con las siglas "CDN" al lado). Ya sabes que el CDN te ofrece un contenido,
en este caso un script Javascript, que est alojado en otro servidor, pero que lo puedes usar desde tu pgina
para mejorar la entrega del mismo.
Nota: La versin minimizada pesa menos en Kb, por lo que ser la adecuada para cualquier sitio que
tengas en produccin. Sin embargo la versin sin comprimir "Uncompressed" tiene el cdigo completo,
con comentarios, sangrado, etc. lo que hace que sea ms fcil de leer por humanos. Puedes usar si lo
deseas la versin sin comprimir en la etapa de desarrollo.
Pgina 18 de 129
Manual de AngularJS
realmente necesario.
Declarar directivas
Hay un paso ms para dejar lista una pgina donde quieras usar AngularJS. Es simplemente colocar la
directiva ng-app en la etiqueta que englobe la aplicacin. Ms adelante hablaremos con ms detalle de las
directivas y daremos algunos tips para usarlas mejor. Por ahora puedes quedarte simplemente con la
necesidad de informar a AngularJS del contenedor HTML donde va a desplegar su "magia".
Tpicamente pondrs ng-app en la etiqueta HTML de inicio del documento.
<!DOCTYPE html>
<html lang="en" ng-app>
<head>
<meta charset="UTF-8">
<title>Ej de AngularJS</title>
</head>
<body>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
</body>
</html>
As como ng-app, existen muchas otras directivas para enriquecer tu HTML, aun veremos alguna ms en
este artculo.
Nota: El cdigo de este Hola Mundo lo puedes encontrar tambin, prcticamente la misma
implementacin, en la home de AngularJS.
Observa que en el campo de texto hemos usado ng-model y le hemos asignado un valor. Ese ng-model es
otra directiva que nos dice que ese campo de texto forma parte de nuestro modelo y el valor "nombre" es la
referencia con la que se conocer a este dato. Insisto en que ms adelante hablaremos con detalle sobre
http://desarrolloweb.com/manuales/manual-angularjs.html
Pgina 19 de 129
Manual de AngularJS
Como ves, dentro del H1 tenemos {{nombre}}. Esas dobles llaves nos sirven para indicarle a AngularJS
que lo que hay dentro es una expresin. All podemos colocar cosas (cdigo) para que Angular resuelva por
nosotros. En este caso estamos colocando simplemente el nombre del modelo o dato que queremos
mostrar.
Cdigo completo
Nuestro ejemplo es perfectamente funcional. Si estabas esperando que escribisemos algo de Javascript,
lamento decepcionarte. La potencia de AngularJS es justamente que muchas cosas se pueden hacer en el
documento HTML simplemente extendiendo sus posibilidades a travs de directivas y expresiones.
Claro que para que esto funcione, por debajo el framework hace muchas cosas, pero de momento no es el
caso extenderse ms.
Puedes ver el cdigo completo a continuacin. Puedes copiarlo y pegarlo tal cual en tu editor de texto, en
un nuevo archivo .html y debera de funcionarte sin ningn problema.
<!DOCTYPE html>
<html lang="en" ng-app>
<head>
<meta charset="UTF-8">
<title>Ej de AngularJS</title>
</head>
<body>
<h1>Hola {{nombre}}</h1>
<div class="contenedor">
<form action="">
Cmo te llamas? <input type="text" ng-model="nombre">
</form>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
</body>
</html>
http://desarrolloweb.com/manuales/manual-angularjs.html
Pgina 20 de 129
Manual de AngularJS
Qu es el binding
El binding no es ms que enlazar la informacin que tenemos en el "scope" con lo que mostramos en el
HTML. Esto se produce en dos sentidos:
One-way binding: En este caso la informacin solamente fluye desde el scope hacia la parte visual, osea,
desde el modelo hacia la representacin de la informacin en el HTML. Lo conseguimos con la sintaxis
"Mustache" de las dos llaves.
{{ dato }}
Ese dato estaras trayndolo desde el scope y mostrndolo en la pgina. La informacin fluye desde el scope
hacia la representacin quiere decir que, si por lo que sea se actualiza el dato que hay almacenado en el
http://desarrolloweb.com/manuales/manual-angularjs.html
Pgina 21 de 129
Manual de AngularJS
En este caso cuando el modelo cambie, el dato que est escrito en el campo de texto (o en el elemento de
formulario donde lo uses) se actualizara automticamente con el nuevo valor. Adems, gracias al doble
binding (two-way) en este caso, cuando el usuario cambie el valor del campo de texto el scope se actualizar
automticamente.
Pgina 22 de 129
Manual de AngularJS
pequeo ejemplo. Suscribirte eventos, definir las funciones manejadoras para que cuando cambie el estado
del campo de texto, volcarlo sobre la pgina. Crear el manejador del botn para que cuando lo pulses se
enve el nuevo texto "hola" tanto al campo de texto como a la pgina, etc.
No estamos diciendo que sea difcil hacer eso "a mano", seguro que la mayora es capaz de hacerlo en
jQuery, pero fjate que para cada una de esas pequeas tareas tienes que agregar varias lneas de cdigo,
definir eventos, manejadores, especificar el cdigo para que los datos viajen de un lugar a otro. Quizs no es
tan complicado, pero s es bastante laborioso y en aplicaciones complejas comienza a resultar un infierno
tener que estar pendiente de tantas cosas.
Otra ventaja, aparte del propio tiempo que ahorras, es una limpieza de cdigo muy destacable, ya que no
tienes que estar implementando muchos eventos ni tienes necesidad de enviar datos de un sitio a otro. Tal
como te viene un JSON de una llamada a un servicio web lo enganchas al scope y automticamente lo
tienes disponible en la vista, lo que es una maravilla. Esto se ve de manera notable en comparacin con
otros frameworks como BackboneJS.
Nota: Osea que el doble binding de Angular nos ahorra mucho trabajo, pero ojo, quizs no sea
necesario para cualquier tipo de aplicacin. Si tus necesidades no son muy grandes igual no consigues
adelantar tanto. Incluso en aplicaciones con inmensa cantidad de datos puede que el doble binding te
pueda ralentizar un poco la aplicacin porque toda esa gestin del binding se haga pesada, igual de
manera innecesaria. En esos casos quizs otra librera funcione mejor que AngularJS. Sin embargo, la
inmensa mayora de las aplicaciones se beneficiarn de ese doble binding.
http://desarrolloweb.com/manuales/manual-angularjs.html
Pgina 23 de 129
Manual de AngularJS
http://desarrolloweb.com/manuales/manual-angularjs.html
Pgina 24 de 129
Manual de AngularJS
AngularJS nos trae una serie de directivas "de fbrica" que nos sirven para hacer cosas habituales, as como
t o terceros desarrolladores pueden crear sus propias directivas para enriquecer el framework.
Nota: Como puedes comprobar, ng-app es una directiva y se indica como si fuera un atributo el
HTML. Pero no lo es ningn atributo real de HTML. Si usas un validador de HTML te advertir que
ese atributo es inexistente y se interpretar por un error de validacin. Para solucionar este posible
inconveniente, la prctica aconsejable es colocar el prefijo "data-" a cada directiva.
<html data-ng-app>
De ese modo tu cdigo validar perfectamente, ya que en HTML5 se pueden crear cualquier tipo de
atributos personalizados que comiencen por "data-" y asignarles cualquier tipo de dato que queramos
almacenar en la etiqueta.
Para no causar confusiones, tambin podemos agregar que a nivel de Javascript las directivas las encontrars
nombradas con notacin "camel case", algo como ngApp. En la documentacin tambin las encuentras
nombradas con camel case, sin embargo, como el HTML no es sensible a las maysculas y minsculas no
tiene tanto sentido usar esa notacin y por ello se separan las palabras de las directivas por un guin "-".
Opcionalmente ngApp puede contener como valor un mdulo de AngularJS a cargar. Esto lo veremos ms
adelante cuando trabajemos con mdulos.
Nota: De nuevo, cabe decir que no forma parte del estndar HTML sino que es una extensin que
tenemos gracias a AngularJS.
La indicas con el atributo del HTML ng-model, asignando el nombre de la variable de tu modelo que ests
declarando.
http://desarrolloweb.com/manuales/manual-angularjs.html
Pgina 25 de 129
Manual de AngularJS
Con eso le ests diciendo al framework que est atento a lo que haya escrito en ese campo de texto, porque
es una una variable que vas a utilizar para almacenar algo y porque es importante para tu aplicacin.
Tcnicamente, lo que haces con ngModel es crear una propiedad dentro del "scope" (tu modelo) cuyo valor
tendr aquello que se escriba en el campo de texto. Gracias al "binding" cuando modifiques ese valor en el
scope por medio de Javascript, tambin se modificar lo que haya escrito en el campo de texto. Aunque
todo esto lo experimentars y entenders mejor un poco ms adelante cuando nos metamos ms de lleno en
los controladores.
Expresiones
Con las expresiones tambin enriquecemos el HTML, ya que nos permiten colocar cualquier cosa y que
AngularJS se encargue de interpretarla y resolverla. Para crear una expresin simplemente la englobas
dentro de dobles llaves, de inicio y fin.
Ahora dentro de tu aplicacin, en cualquier lugar de tu cdigo HTML delimitado por la etiqueta donde
pusiste la directiva ng-app eres capaz de colocar expresiones. En Angular podemos una gama de tipos de
expresiones, de momento hagamos una prueba colocando una expresin as.
<h1>{{ 1 + 1}}</h1>
Angular cuando se pone a ejecutar la aplicacin buscar expresiones de este estilo y lo que tengan dentro, si
es algo que l pueda evaluar, lo resolver y lo sustituir con el resultado que corresponda.
Puedes probar otra expresin como esta:
{{ "Hola " + "DesarrolloWeb" }}
Al ejecutarlo, AngularJS sustituir esa expresin por "Hola DesarrolloWeb". Estas expresiones no me
aportan gran cosa de momento, pero luego las utilizaremos para ms tipos de operaciones.
Lo habitual de las expresiones es utilizarlas para colocar datos de tu modelo, escribiendo los nombres de las
"variables" que tengas en el modelo. Por ejemplo, si tienes este cdigo HTML, donde has definido un dato
en tu modelo llamado "valor":
<input type="text" ng-model="valor" />
Podrs volcar en la pgina ese dato (lo que haya escrito en el campo INPUT) por medio de la siguiente
expresin:
{{valor}}
http://desarrolloweb.com/manuales/manual-angularjs.html
Pgina 26 de 129
Manual de AngularJS
Otro detalle interesante de las expresiones es la capacidad de formatear la salida, por ejemplo, diciendo que
lo que se va a escribir es un nmero y que deben representarse dos decimales necesariamente. Vemos
rpidamente la sintaxis de esta salida formateada, y ms adelante la utilizaremos en diversos ejemplos:
{{ precio | number:2 }}
Cabe decir que estas expresiones no estn pensadas para escribir cdigo de tu programa, osea, lo que
llamamos lgica de tu aplicacin. Como decamos, estn sobre todo pensadas para volcar informacin que
tengas en tu modelo y facilitar el "binding". Por ello, salvo el operador ternario (x ? y : z), no se pueden
colocar expresiones de control como bucles o condicionales. Sin embargo, desde las expresiones tambin
podemos llamar a funciones codificadas en Javascript (que estn escritas en los controladores, como
veremos enseguida) para poder resolver cualquier tipo de necesidad ms compleja.
Hasta aqu hemos descrito todos los componentes de AngularJS que ya conociste en el artculo de los
Primeros pasos con AngularJS. Ahora vamos a conocer otros componentes de las aplicaciones que
podemos hacer con este framework Javascript.
http://desarrolloweb.com/manuales/manual-angularjs.html
Pgina 27 de 129
Manual de AngularJS
Directiva ngInit
Esta directiva nos sirve para inicializar datos en nuestra aplicacin, por medio de expresiones que se
evaluarn en el contexto actual donde hayan sido definidas. Dicho de otra manera, nos permite cargar cosas
en nuestro modelo, al inicializarse la aplicacin.
As de manera general podemos crear variables en el "scope", inicializarlas con valores, etc. para que en el
momento que las vayas a necesitar estn cargadas con los datos que necesitas.
Con esto consigues que tu aplicacin inicialice en el scope un dato llamado miArrayDatos como un array
vaco. Pero no le prestes demasiada atencin al hecho de haber colocado la directiva ngInit dentro de la
misma etiqueta que inicializa la aplicacin, pues podra ir en cualquier otra etiqueta de tu HTML. Realmente,
colocarla en esa divisin marcada con ngApp es considerado una mala prctica. Ten en cuenta lo siguiente
cuando trabajes con ngInit:
El nico caso apropiado donde se debera de usar ngInit es en enlace de propiedades especiales de
ngRepeat. Si lo que quieres es inicializar datos en tu modelo para toda la aplicacin, el lugar apropiado sera
en el controlador. Enseguida vemos un ejemplo de uso apropiado, cuando conozcamos la directiva
ngRepeat.
Nota: Aclaramos ya que en el ejemplo final de este artculo vamos a usar ngInit para asociar datos al
scope, e inicializarlos. Sin embargo, debemos de ser conscientes que para ello deberamos usar un
controlador. Como no hemos llegado a los controladores todava, y queremos limitarnos solo a trabajar
con el HTML, nos sirve como mtodo alternativo.
http://desarrolloweb.com/manuales/manual-angularjs.html
Pgina 28 de 129
Manual de AngularJS
Directiva ngRepeat
Esta directiva te sirve para implementar una repeticin (un bucle). Es usada para repetir un grupo de
etiquetas una serie de veces. Al implementar la directiva en tu HTML tienes que decirle sobre qu estructura
se va a iterar. ngRepeat se usa de manera muy habitual y se ver con detenimiento en decenas de ejemplos.
De momento puedes quedarte que es como un recorrido for-each en el que se itera sobre cada uno de los
elementos de una coleccin.
La etiqueta donde has colocado el atributo ng-repeat y todo el grupo de etiquetas anidadas dentro de sta,
funciona como si fuera una plantilla. Al procesarse el compilador HTML de AngularJS el cdigo HTML de
esa plantilla se repite para cada elemento de la coleccin que se est iterando. Dentro de esa plantilla tienes
un contexto particular, que es definido en la declaracin de la directiva, que equivale al elemento actual en el
bucle. Se ve mejor con un ejemplo.
<p ng-repeat="elemento in miColeccion">
Ests en: <span>{{elemento}}</span>
</p>
El dato miColeccion sera un dato de tu modelo, habitualmente un array sobre el que puedas iterar, una vez
por cada elemento. Pero tambin podra ser un objeto y en ese caso la iteracin se realizara en cada una de
sus propiedades.
En lo relativo al contexto prpio del bucle te puedes fijar que dentro de la iteracin podemos acceder al
dato "elemento", que contiene como valor, en cada repeticin, el elemento actual de la coleccin sobre el
que se est iterando.
Esta directiva es bastante sofisticada y explicar cada una de sus posibilidades nos llevara algo de tiempo. Sin
embargo, vamos a mostrar cmo podemos trabajar con ngRepeat en conjunto con ngInit, para completar la
explicacin de punto anterior.
<p ng-repeat="elemento in miColeccion" ng-init="paso=$index;">
Elemento con id {{paso}}: <span>{{elemento}}</span>
</p>
La directiva ngRepeat maneja una serie de propiedades especiales que puedes inicializar para el contexto
propio de cada repeticin. Para inicializarlas usamos la directiva ngInit indicando los nombres de las
variables donde vamos a guardar esas propiedades. En este caso estamos indicando que dentro de la
repeticin vamos a mantener una variable "paso" que tendr el valor de $index, que equivale al nmero
ndice de cada repeticin. Osea, en la primera iteracin paso valdr cero, luego valdr uno y as todo
seguido. Igual que tienes $index, Angular te proporciona otras propiedades tiles como $first (que valdr
true en caso que sea la primera iteracin) o $last (true solo para la ltima iteracin)
Nota: El que acabas de ver sera el nico uso de ngInit considerado como buena prctica, en conjunto
con ngRepeat para inicializar sus propiedades.
http://desarrolloweb.com/manuales/manual-angularjs.html
Pgina 29 de 129
Manual de AngularJS
Dejamos de momento ngRepeat, aunque vuelvo a sealar que hay otra serie de cosas interesantes en la
directiva para las repeticiones, como filtros, rdenes, etc.
Directiva ngClick
Terminamos nuestra dosis de teora con una explicacin de la directiva ngClick. Como podrs imaginarte es
utilizada para especificar un evento click. En ella pondremos el cdigo (mejor dicho la expresin) que se
debe ejecutar cuando se produzca un clic sobre el elemento donde se ha colocado la directiva.
Tpicamente al implementar un clic invocars una funcin manejadora de evento, que escribirs de manera
separada al cdigo HTML.
<input type="button" value="Haz Clic" ng-click="procesarClic()">
Esa funcin procesarClic() la escribirs en el controlador, factora, etc. Sera el modo aconsejado de
proceder, aunque tambin podras escribir expresiones simples, con un subconjunto del cdigo que podras
escribir con el propio Javascript. Incluso cabe la posibilidad de escribir varias expresiones si las separas por
punto y coma.
<input type="button" value="haz clic" ng-click="numero=2; otraCosa=dato " />
No difiere mucho a como se expresan los eventos clic en HTML mediante el atributo onclick, la diferencia
aqu es que dentro de tus expresiones podrs acceder a los datos que tengas en tu modelo.
Nota: Aunque tcnicamente pueda escribir expresiones directamente en el cdigo HTML, en el valor
del atributo ng-click, tienes que evaluar con cuidado qu tipo de cdigo realizas porque dentro de la
filosofa de AngularJS y la del MVC en general, no puedes escribir en tu HTML cdigo que sirva para
implementar la lgica de tu aplicacin. (El cdigo que necesitas para hacer las funcionalidades de tu
aplicacin no lo colocas en la vista, lo colocas en el controlador).
Nota: Como advertimos al principio del artculo, solo voy a usar cdigo HTML para este ejercicio. Por
ese motivo hay un par de cosas que no seran consideradas buenas prcticas, como el uso de ngInit para
inicializar el array "pensamientos" y el hecho de haber colocado dentro de un ng-click expresiones que
sera mejor haber escrito en una funcin de nuestro controlador.
En esta aplicacin tenemos un campo de texto para escribir cualquier cosa, un "pensamiento". Al pulsar
sobre el botn se agregar dentro de un array llamado "pensamientos" lo que se haya escrito en el campo de
http://desarrolloweb.com/manuales/manual-angularjs.html
Pgina 30 de 129
Manual de AngularJS
texto. Adems encuentras un bucle definido con ng-repeat que itera sobre el array de "pensamientos"
mostrando todos los que se hayan agregado.
<div ng-app ng-init="pensamientos = [];">
<h1>Altavoz AngularJS</h1>
<p>
Qu hay de nuevo?
<br />
<input type="text" ng-model="nuevoPensamiento" />
<input type="button" value="Agregar" ng-click="pensamientos.push(nuevoPensamiento); nuevoPensamiento = '';" />
</p>
<h2>Pensamientos que has tenido</h2>
<p ng-repeat="pensamiento in pensamientos" ng-init="paso = $index">
Pensaste esto: {{pensamiento}} (Iteracin con ndice {{paso}})
</p>
</div>
El dato del array "pensamientos" lo generas en el scope con el ng-init de la primera etiqueta. En el campo
de texto tenemos la directiva ng-model para indicarle que lo que se escriba formar parte de nuestro modelo
y se almacenar en la variable nuevoPensamiento. Como ves, en el ng-click se hace un push de ese nuevo
pensamiento dentro del array de pensamientos. En ng-repeat se itera sobre la coleccin de pensamientos,
escribindolos todos por pantalla, junto con el ndice de ese pensamiento actual en el array "pensamientos".
Puedes ponerlo en marcha y jugar un poco con la aplicacin haciendo tus cambios para calmar tu curiosidad
o responder posibles dudas.
http://desarrolloweb.com/manuales/manual-angularjs.html
Pgina 31 de 129
Manual de AngularJS
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.24/angular.min.js"></script>
</body>
</html>
Pgina 32 de 129
Manual de AngularJS
http://desarrolloweb.com/articulos/videotutoriales-angularjs-directivas-html-ejemplos-practicos.html
El cdigo es el siguiente:
<!DOCTYPE html>
<html lang="en" ng-app>
<head>
<meta charset="UTF-8">
<title>hola mundo en Angular</title>
</head>
<body>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.24/angular.min.js"></script>
</body>
</html>
3) Directiva ngClick
En este tercer vdeo vamos a explicar la directiva ngClick que ya nos permite agregar algo de interaccin en
los elementos de la pgina. Colocaremos un botn y dentro de l el atributo ng-click que nos permitir
asignarle un comportamiento.
Aclaramos en el vdeo que no es la manera ms recomendable de actuar, puesto que los comportamientos
deberan escribirse (su cdigo) dentro de los controladores. No obstante nos ofrece una idea de las
posibilidades de AngularJS y est bien para comenzar a dar los primeros pasos.
Mediante el botn escribimos dos comportamientos en el vdeo (aunque en el cdigo fuente que tenemos
solo se conserv uno de los comportamientos). El primero que vers en la grabacin es asignarle un valor al
campo SELECT. De ese modo se muestra cmo el campo de seleccin pierde el valor a null con el que lo
inicializa automticamente AngularJS. En el segundo comportamiento simplemente se coloca un nuevo
texto en el campo de texto.
Pgina 33 de 129
Manual de AngularJS
<!DOCTYPE html>
<html lang="en" ng-app>
<head>
<meta charset="UTF-8">
<title>hola mundo en Angular</title>
</head>
<body>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.24/angular.min.js"></script>
</body>
</html>
Estos son los tres ejemplos que te mostramos por ahora, aunque la sesin se complet con dos nuevas
muestras de uso de AngularJS, en las que se mostr cmo crear un controlador. Sin embargo, como no
hemos visto controladores todava en este manual, nos reservamos para un poco ms adelante comentarte
acerca de esos vdeos. Si te interesan, lo nico que debes hacer es irte a la lista de reproduccin de los
videotutoriales de Angular en nuestro canal de Youtube.
En el siguiente artculo continuaremos hablando de modelos y luego de controladores, con lo que
podremos comenzar a ver cdigo fuente Javascript con buenas prcticas, en vez de mezclar la interaccin
con la presentacin, tal como nos hemos obligado a hacer con lo que sabemos en estos primeros pasos con
la librera Javascript.
De momento te sugiero que practiques por tu cuenta y trates de hacer ejemplos como stos u otros ms
complejos que se te ocurran, pues con la prctica es como se afianzan los conocimientos. Observars que
jugar con AngularJS se hace muy divertido y que se consiguen comportamientos interesantes con muy poco
o ningn cdigo Javascript.
http://desarrolloweb.com/manuales/manual-angularjs.html
Pgina 34 de 129
Manual de AngularJS
Nota: La manera recomendada de arrancar la aplicacin es con la directiva ngApp, aunque tambin
podras si lo deseas arrancarla con el mtodo angular.bootstrap().
http://desarrolloweb.com/manuales/manual-angularjs.html
Pgina 35 de 129
Manual de AngularJS
En ese caso se supone que para identificar tu aplicacin dentro del DOM le has colocado un identificador
"miapp". Aprecia tambin que los mdulos son opcionales e incluso que podra haber varios mdulos que
deseas arrancar, algo posible, pero raramente usado.
Recuerda que hasta ahora, en lo que llevamos del Manual de AngularJS, en la directiva ngApp, atributo ngapp, no colocbamos ningn valor. Eso era porque hasta el momento no habamos trabajado con mdulos.
Sin embargo, a partir de ahora que los aprendemos a utilizar recuerda que los vas a tener que indicar al
arrancar la aplicacin.
Nota: Aunque en varios lugares de este manual nos podamos referir a ngApp como "directiva"
queremos aclarar que realmente no lo es. La propia documentacin de AngularJS tambin la llama as,
pero simplemente es un atributo y sirve para arrancar desde la function BootStrap, que es llamada desde
la function angularInit. https://github.com/angular/angular.js/blob/master/src/Angular.js Tampoco
queremos liarte de momento con estos detalles, solo era una aclaracin que pensamos es importante
hacer.
Creacin de mdulos
Desde Javascript crears los mdulos usando el mtodo angular.module() e indicndole una serie de
parmetros. Echa un vistazo a esta sintaxis.
angular.module('miAplicacion', [ ... ], function(...){ ... })
La variable "angular" la tienes como variable global cuando cargas AngularJS, dentro tiene un objeto que
estar disponible en cualquier parte de tu cdigo. Luego ves "module", que es un mtodo del objeto
"angular" y que sirve para crear el mdulo. El primer argumento es el nombre del mdulo, que corresponde
con el nombre de tu aplicacin. En el segundo parmetro puedes indicar una serie de mdulos adicionales,
separados por comas, que seran tus dependencias. Pueden ser mdulos de otros autores o puede que t
mismo hayas decidido organizar tu cdigo en diferentes mdulos. El tercer parmetro es opcional y en l
colocamos una funcin que sirve para configurar AngularJS.
Para comenzar crears tus mdulos probablemente de una manera sencilla, tal como puedes ver a
continuacin:
angular.module('nuevaApp', []);
http://desarrolloweb.com/manuales/manual-angularjs.html
Pgina 36 de 129
Manual de AngularJS
El objeto module
Esta llamada a angular.module() te devuelve un objeto module, que tiene una serie de mtodos como
config, run, provider, service, factory, directive, controller, value, etc. que son los que nos sirven para
controlar la lgica de presentacin y la lgica de negocio. Vers dos variantes de cdigo en este sentido:
OPCIN 1) Puedes "cachear" (almacenar) el mdulo en una variable y luego usarlo para crear tus
controladores, factoras, etc.
var nuevaApp = angular.module('nuevaApp', []);
nuevaApp.controller( ... );
OPCIN 2) Aunque en muchos casos vers que ese objeto module ni siquiera se guarda en una variable,
sino que se encadenan las creaciones de los controladores o factoras todo seguido. A esto ltimo se suele
llamar estilo "Fluent"
angular
.module('nuevaApp', [])
.controller( ... )
.factory( ... );
Estas dos opciones proponen estilos de cdigo distintos. En la segunda opcin, al encadenar las llamadas
desde la creacin del mdulo hasta los controladores u otras cosas que necesitemos, nos estamos ahorrando
la creacin de una variable global, eliminando posibilidad de que colisione con otras del mismo nombre que
haya en otras partes de tu aplicacin. Como te imaginars, se recomienda la OPCIN 2).
Nota: Los mdulos tienen mucha importancia en AngularJS, por lo que aprenderemos a hacer muchas
cosas con ellos. De momento me interesan para crear controladores y poder avanar un poco en los
ejemplos prcticos del Manual de AngularJS, as que no nos vamos a detener mucho en ellos todava.
http://desarrolloweb.com/manuales/manual-angularjs.html
Pgina 37 de 129
Manual de AngularJS
Por si no has visto la diferencia con angular.module('nombreModulo', []) creamos un mdulo y con
angular.module('nombreModulo') recuperamos un mdulo que haya sido creado anteriormente con el
nombre 'nombreModulo'.
Mdulos en adelante
Me gustara terminar el artculo con un ejemplo prctico de uso mdulos en AngularJS pero si utilizamos
simplemente el nuevo conocimiento de este artculo sera complicado. En realidad los mdulos sirven como
base para implementar muchas cosas en AngularJS, por lo que enseguida les sacaremos bastante provecho.
En el siguiente artculo nos introduciremos en los controladores y comenzaremos a utilizar el famoso
"scope". Para todo ello es condicin indispensable comenzar con un mdulo, as que las prcticas en esta
ocasin las dejaremos para ms adelante.
Nota: Los que ya conocen el MVC podrn hacerse una idea ms concreta del cometido de los
controladores. Si no es tu caso, no te preocupes porque en futuros artculos podrs leer de manera
terica el MVC y de manera particular cmo se aplica este paradigma en AngularJS. Para los que no
sepan MVC y quieran aprender de qu se trata en general, recomendamos la lectura del artculo sobre el
paradigma MVC.
http://desarrolloweb.com/manuales/manual-angularjs.html
Pgina 38 de 129
Manual de AngularJS
Un controlador puede ser agregado al DOM mediante la directiva ngController (con el atributo ngcontroller en la etiqueta HTML) y a partir de entonces tendremos disponible en esa etiqueta (y todas sus
hijas) una serie de datos. Esos datos son los que necesitars en la vista para hacer la parte de presentacin y
es lo que asociaramos en el MVC con el "modelo". En la terminologa de Angular al modelo se le llama
"scope" y dentro de poco vamos a explicarlo un poco mejor.
A los controladores podemos inyectarles valores o constantes. Como su propio nombre indica, las
constantes son las que no van a cambiar a lo largo del uso de la aplicacin y los valores son aquellas
variables cuyo dato puede cambiar durante la ejecucin de una aplicacin. Tambin podremos inyectar
servicios y factoras, componentes muy parecidos entre s y que veremos ms adelante.
Nota: Sin entrar a describir de momento lo que son "services" y "factories" puedes simplemente
recordar que su utilidad es la de encapsular cdigo.
Concepto de Scope
Para poder introducir los controladores debemos detenernos antes en un concepto que se repite hasta la
saciedad dentro de la literatura de AngularJS, el "scope". De hecho, tal como dice la documentacin de
AngularJS, el cometido de un controlador consiste en desempear una funcin constructora capaz de
aumentar el Scope.
El "scope" es la pieza ms importante del motor de AngularJS y es donde estn los datos que se
tienen que manejar dentro de la parte de presentacin.
El scope es un gran contenedor de datos, que transporta y hace visible la informacin necesaria para
implementar la aplicacin, desde el controlador a la vista y desde la vista al controlador. En trminos de
cdigo el scope no es ms que un objeto al que puedes asignar propiedades nuevas, con los datos que
necesites, o incluso con funciones (mtodos).
Esos datos y esas funciones estn visibles tanto en el Javascript de los controladores como en el HTML de
las vistas, sin que tengamos que realizar ningn cdigo adicional, pues Angular ya se encarga de ello
automticamente. Adems, cuando surgen cambios en los datos se propagan entre los controladores y las
vistas automticamente. Esto se realiza por un mecanismo que llamamos "binding", y en AngularJS tambin
"doble binding" (en espaol sera enlace), que explicaremos con detalle en futuros artculos.
As pues, desde los controladores vamos a ser capaces de trabajar con el scope de una manera minuciosa,
http://desarrolloweb.com/manuales/manual-angularjs.html
Pgina 39 de 129
Manual de AngularJS
Nota: Hasta el momento en este Manual de AngularJS hemos usado el scope en varias ocasiones y ya
hemos dicho que representa al modelo, del paradigma MVC. Siempre que hemos usado el scope en
HTML ha sido 1) agregando partes de la pgina al modelo mediante la directiva ngModel, por ejemplo
datos que se escriban en un campo de texto o se selecionen en un campo select, o 2) volcando
informacin en el HTML mediante expresiones escritas entre dos llaves {{ }}.
Todo eso estaba muy bien, sin embargo en trminos de programacin necesitamos un lugar donde escribir
todo el Javascript necesario para implementar la lgica de la aplicacin. Integrar el Javascript dentro del
HTML no es nada recomendable, por diversos motivos que ya se conocen. Ya dijimos adems que dentro
del cdigo HTML, no se puede (o mejor dicho, no se debera) hacer clculos, asignaciones de valores y en
resumen cdigo que represente la lgica de nuestras aplicaciones. Todo ello ir en los controladores.
scope.metodoScope = function(){
scope.datoScope = "otra cosa";
}
});
http://desarrolloweb.com/manuales/manual-angularjs.html
Pgina 40 de 129
Manual de AngularJS
Como puedes comprobar, resulta un tanto complejo. Adems tenemos que explicarte cmo se engancha
este controlador dentro del cdigo HTML. Para explicar todo eso con calma necesitamos alargarnos
bastante, as que lo veremos en el siguiente artculo. Adems, te explicaremos varias alternativas de cdigo
para trabajar con controladores que se usan habitualmente en AngularJS, con mejores y peores prcticas.
http://desarrolloweb.com/manuales/manual-angularjs.html
Pgina 41 de 129
Manual de AngularJS
En este punto queremos aclarar que existen diversas alternativas de cdigo para crear el Javascript necesario
para definir nuestro controlador. Vamos a comenzar por una que es muy habitual de ver en diversos
tutoriales y documentacin, aunque no es la mejor. Todas las formas funcionan, pero hay algunas que en
determinadas circunstacias pueden ser mejores. Luego las estudiaremos y explicaremos el motivo por el que
seran todava ms recomendadas para crear tus controladores.
Nota: El objetivo de este primer controlador es simplemente observar cul es el cdigo y la sintaxis
para crearlos. Realmente observars es un controlador muy tonto, pero espero me disculpes.
Buscaremos ms adelante ejemplos ms tiles.
OPCIN 1)
angular
.module('pruebaApp', [])
.controller('pruebaAppCtrl', function($scope){
$scope.algo = "Hola Angular, usando controller ms simple";
});
De esta manera estoy creando un mdulo llamado "pruebaApp". Sobre el mdulo invoco el mtodo
controller() y creo un controlador llamado "pruebaAppCtrl". En la creacin del controlador vers que se
especifica una funcin, ella es la que hace de constructora de nuestro controlador. A esa funcin le llega
como parmetro $scope que es el nombre de variable donde tendrs una referencia al conodido "scope" que
almacena los datos de mi modelo.
Dentro de la funcin del controlador hacemos poca cosa. De momento simplemente le asigno un valor a un
atributo de $scope. He creado un atributo nuevo en el objeto $scope que no exista y que se llama "algo"
($scope.algo). Con ello simplemente le estoy agregando un dato al modelo. Gracias al "binding" o enlace,
ese dato luego lo podr utilizar en el HTML.
De hecho, queremos ya echarle un vistazo al HTML que podramos tener para usar este controller.
<div ng-app="pruebaApp" ng-controller="pruebaAppCtrl">
{{algo}}
</div>
Como puedes ver, en el HTML indicamos el nombre del mdulo que se usar para implementar esta
aplicacin (que corresponde con el nombre del mdulo creado en el cdigo Javascript) y el nombre del
controlador (tambin corresponde con el nombre del controller que he creado con Javascript). Adems en
el HTML podrs encontrar la expresin {{algo}} que lo que hace es volcar como texto en la pgina el
contenido de la variable "algo". Esa variable pertenece al scope y la hemos inicializado en el cdigo del
controller.
El resultado es que en nuestra pgina aparecer el texto "Hola Angular, usando controller", que es el valor
que fue asignado en el atributo "algo" de $scope. De momento la aplicacin no es nada espectacular pero lo
http://desarrolloweb.com/manuales/manual-angularjs.html
Pgina 42 de 129
Manual de AngularJS
VARIANTE OPCIN 1)
Existe una variante de este mismo ejemplo, al crear el controlador, que deja nuestro cdigo un poco ms
complejo, pero que ayuda en determinadas circunstancias. La clave aqu son los minimificadores de
Javascript (o minificadores), que sabemos que reducen el peso en bytes del cdigo compactndolo de
distintas maneras. Si los usas, el cdigo que hemos visto en el anterior apartado puede dar errores una vez
minimificado.
El problema qte puede surgir est en la inyeccin del $scope, que se recibe como parmetro en la funcin
constructora del controller.
function($scope)
Angular, al ver el nombre del parmetro "$scope", sabe perfectamente lo que tiene que inyectar en ese lugar.
Sin embargo, una vez minimificado, el nombre de esa variable "$scope" puede haberse cambiado por algo
como "a", lo que hara imposible que el framework sepa lo que debe de enviar. Eso se soluciona con un
cdigo como el siguiente.
angular
.module('pruebaApp', [])
.controller('pruebaAppCtrl', ['$scope', function($scope){
$scope.algo = "Hola Angular, usando controller!";
}]);
En este caso, en la llamada al mtodo que crea el controlador, controller(), ves un array que nos sirve para
inyectar las dependencias.
['$scope', function($scope){ ... }]
En este caso le estamos diciendo que el primer parmetro del controlador es '$scope', gracias al primer
elemento del array. Como las cadenas como '$scope' no se alteran despus de la minimizacin, podemos
estar seguros que le llegarn perfectamente a Angular. Entonces sabr que en el primer parmetro de la
funcin constructora del controlador esperas recibir el $scope'. Esto ser as independientemente del
nombre de la variable que se uses como primer parmetro.
Es cierto que la sintaxis parece un poco rebuscada, pero poco a poco te acostumbrars, pues realmente es
muy repetitivo.
Nota: Esto que acabamos de explicar para el tema de la inyeccin de dependencias sirve igual con
muchos otros elementos que podras necesitar en tus controladores. Osea, puedes inyectar del mismo
modo otras cosas aparte del $scope, como $http, etc. Esta variante de la opcin 1, debido al modo de
declarar la inyeccin de dependencias, es ms adecuada y es algo retomaremos tambin en futuras
entregas de este manual.
http://desarrolloweb.com/manuales/manual-angularjs.html
Pgina 43 de 129
Manual de AngularJS
OPCIN 2)
He colocado como primera opcin porque es ms habitual en tutoriales y puedes haberla ledo en la
documentacin del framework o en diversas presentaciones por ah. Sin embargo, es ms recomendada esta
segunda alternativa que os presentamos a continuacin.
angular
.module('pruebaApp', [])
.controller("pruebaAppCtrl", function(){
this.algo = "Esto funciona! Gracias Angular";
});
Como estars observando, el controlador es prcticamente igual. Ahora la diferencia es que no ests
inyectando el $scope. Ahora el contexto donde adjuntar las variables que queremos enviar a la vista no lo
sacamos de $scope, sino que lo obtenemos directamente a travs de la variable "this".
En este caso, para cargar un nuevo dato al modelo, llamado "algo", lo hacemos a travs de this.algo y le
asignamos aquello que deseemos.
Esta alternativa implica algn cambio en el HTML con respecto a lo que vimos anteriormente.
<div ng-app="pruebaApp" ng-controller="pruebaAppCtrl as vm">
{{vm.algo}}
</div>
En este caso estamos dicindole no solo el nombre del controlador, sino adems estamos informando que
dentro de ese DOM el scope ser conocido con la variable "vm". Por tanto, ahora cuando deseemos
acceder a datos de ese modelo que nos ofrece el controlador debemos indicar el nombre del scope.
{{vm.algo}}
Nota: La recomendacin de esta opcin 2 se basa en que as puedes tener varios controladores en tu
pgina, incluso anidados unos dentro de otros, y los datos que nos ofrece cada uno estn separados en
distintos espacios de nombres. Esto quizs ahora no te dice nada, pero s que evita en el futuro
habituales problemticas de desarrollo con AngularJS.
http://desarrolloweb.com/manuales/manual-angularjs.html
Pgina 44 de 129
Manual de AngularJS
Ahora que hemos visto estas dos opciones y dado que nos recomiendan la segunda, la utilizaremos de
manera preferente a lo largo del manual. De momento esto es todo, esperamos que con lo que sabes ya
tengas ideas para ir probando nuevos ejemplos. Nosotros en el siguiente artculo crearemos un controlador
que ser un poco ms complejo y til.
Acabamos este artculo con un vdeo de nuestro canal de Youtube donde encontrars ms informacin
sobre la creacin de controladores en AngularJS. Veremos diferentes variantes del cdigo realizadas en
directo. Tambin encontrars explicaciones ofrecidas por varios compaeros expertos en este framework
Javascript.
Puedes ver el ejercicio en marcha en Codepen antes de pasar a estudiar y explicar el cdigo con el que se ha
hecho.
Cdigo HTML
Veamos primero la parte del HTML usada para resolver este ejercicio.
http://desarrolloweb.com/manuales/manual-angularjs.html
Pgina 45 de 129
Manual de AngularJS
Nota: Por si no te has dado cuenta, el espacio de nombres donde tendremos al scope se ha nombrado
como "vm". Ya dijimos que se puede usar cualquier nombre de varialble, eso es lo de menos, lo que
queremos que se note es que "vm" son las siglas de "View Model", osea, el "modelo de la vista". Es algo
que tiene que ver con el paradigma MVC en la variante en la que trabajamos con Angular. Hablaremos
de eso ms adelante.
http://desarrolloweb.com/manuales/manual-angularjs.html
Pgina 46 de 129
Manual de AngularJS
Cdigo Javascript
Ahora pasemos a la parte donde codificamos nuestro Javascript para darle vida a este ejercicio.
angular
.module('acumuladorApp', [])
.controller("acumuladorAppCtrl", controladorPrincipal);
function controladorPrincipal(){
//esta funcin es mi controlador
var scope = this;
scope.total = 0;
scope.cuanto = 0;
scope.sumar = function(){
scope.total += parseInt(scope.cuanto);
}
scope.restar = function(){
scope.total -= parseInt(scope.cuanto);
}
};
http://desarrolloweb.com/manuales/manual-angularjs.html
Pgina 47 de 129
Manual de AngularJS
Nota: Tambin hay varias aproximaciones para definir este Javascript con los modulos y controladores
de Angular. Es recomendable la creacin de una envoltura para tu Javascript, por medio de una funcin
que se autoinvoca. Esto lo veremos ms adelante, puesto que no queremos complicar ms el cdigo
todava.
Con eso tenemos el ejercicio completo, todo lo dems para que esto funcione es tarea de AngularJS. De
manera declarativa en el HTML hemos dicho qu son las cosas con las que se va a trabajar en la aplicacin y
luego hemos terminado de definir e inicializar los datos en el controlador, as como escribir en cdigo las
funcionalidades necesarias para que el ejercicio tome vida.
El cdigo Javascript
var acumuladorApp = angular.module('acumuladorApp', []);
acumuladorApp.controller("acumuladorAppCtrl", ["$scope", function($scope){
//esta funcin es mi controlador
//var $scope = this;
$scope.total = 0;
$scope.cuanto = 0;
$scope.sumar = function(){
$scope.total += parseInt($scope.cuanto);
}
http://desarrolloweb.com/manuales/manual-angularjs.html
Pgina 48 de 129
Manual de AngularJS
$scope.restar = function(){
$scope.total -= parseInt($scope.cuanto);
}
}]);
No comento el cdigo ms, pues es muy parecido al anterior, simplemente se deja de usar el espacio de
nombres y al definir la funcin del controlador se inyecta el $scope de otra manera. Te dejo a ti la tarea de
encontrar todas las diferencias.
http://desarrolloweb.com/manuales/manual-angularjs.html
Pgina 49 de 129
Manual de AngularJS
Existen tres posibles variantes de tipos que acepta la directiva ngClass y que podemos usar siempre que
deseemos.
Asignarle una propiedad del scope que sea una cadena de texto. En este caso esa cadena se coloca
como valor en el atributo class. Si en esa cadena existen varios nombres de clases separados por un
espacio en blanco, esas clases se aplicarn en conjunto al elemento.
Asignarle una propiedad del scope que contenga un array de cadenas. En ese caso se asignan como
clases todos los nombres que haya en las casillas del array.
Asignarle como valor a ng-class un objeto. En ese caso tendr pares clave valor para especificar
nombres de clases y expresiones que deban cumplirse para que stas se apliquen. Lo veremos mejor
con un ejemplo.
Ahora veremos ejemplos de cada una de las tres posibilidades comentadas.
http://desarrolloweb.com/manuales/manual-angularjs.html
Pgina 50 de 129
Manual de AngularJS
Ejemplo 1) Asignar una propiedad del scope que contiene una cadena
Es tan sencillo como indicar esa propiedad dentro del atributo ng-class, como se ve a continuacin.
<h1 ng-class="vm.tamTitular">Acumulador</h1>
<select ng-model="vm.tamTitular">
<option value="titularpeq">Peque</option>
<option value="titulargran">Gran</option>
</select>
Como puedes ver, tenemos un encabezado H1 con ng-class asignado a vm.tamTitular. Esa propiedad del
scope se cre a partir de un campo SELECT que est a continuacin. Por tanto, cuando cambie el option
seleccionado en el campo, cambiar la class asociada al elemento H1.
Tal como habrs deducido, las dos posibles class que se le van a asignar al encabezado sern los value de los
OPTION.
Luego podremos asociar ese array de cadenas, colocando todos los nombres de clases a un elemento de la
pgina con la directiva ngClass.
<h2 ng-class="vm.clases">Control de operacin:</h2>
Como resultado de esa directiva a nuestro encabezado H2 se le van a aplicar las tres clases "uno", "dos" y
"tres".
Este prrafo nos muestra un valor total de una cuenta. Ese valor lo sacamos de la propiedad vm.total y esa
misma propiedad es la que usamos para definir la clase de CSS que vamos a asociar como estilo al prrafo.
http://desarrolloweb.com/manuales/manual-angularjs.html
Pgina 51 de 129
Manual de AngularJS
Ahora echa un vistazo al atributo ng-class y vers que lo que le indicamos es un objeto, pues est entre
llaves. Ese objeto tiene un nmero de pares clave/valor indeterminado, puede ser uno o varios. Cada uno
de esos pares clave/valor nos sirven para definir si debe o no aplicarse una clase en concreto.
En la clave colocas el nombre de la clase, class de tu CSS, que Angular puede colocar si se cumple una
expresin boleana. Como valor colocamos la expresin boleana a evaluar por AngularJS para que el sistema
deduzca si se debe aplicar esa clase o no.
En nuestro ejemplo se aplicar la clase "positivo" en caso que la propiedad vm.total sea mayor o igual que
cero. Se aplicar la clase "negativo" en caso que la propiedad vm.total tenga un valor menor que cero.
Nota: Para la realizacin de este cdigo hemos partido como base del ejemplo relatado en el artculo
Segundo ejercicio con controller en AngularJS. En realidad solo hemos agregado los tres posibles usos
de la directiva ngClass explicados en este artculo.
Ahora puedes ver el cdigo CSS con la definicin de varias clases con las que vamos a jugar.
.negativo {
color: red;
}
.positivo {
color: #33f;
http://desarrolloweb.com/manuales/manual-angularjs.html
Pgina 52 de 129
Manual de AngularJS
}
.titularpeq{
font-size: 10pt;
}
.titulargran{
font-size: 18pt;
}
.uno{
background-color: #666;
}
.dos{
color: #fff;
}
.tres{
font-size: 30px;
}
Por ltimo el cdigo Javascript de nuestro controlador. Como deca, encontrars diversas cosas adicionales
a las comentadas en este artculo, pero no te deben extraar porque fueron explicadas anteriormente en el
Manual de AngularJS.
angular
.module('acumuladorApp', [])
.controller("acumuladorAppCtrl", controladorPrincipal);
function controladorPrincipal(){
//esta funcin es mi controlador
var vm = this;
vm.total = 0;
//scope.cuanto = 0;
vm.tamTitular = "titularpeq"
vm.sumar = function(){
vm.total += parseInt(vm.cuanto);
}
vm.restar = function(){
vm.total -= parseInt(vm.cuanto);
}
vm.clases = ["uno", "dos", "tres"];
};
Eso es todo, esperamos que puedas disfrutar de esta til directiva en tus proyectos. Con un poco de
imaginacin comprobars la potencia de ngClass.
http://desarrolloweb.com/manuales/manual-angularjs.html
Pgina 53 de 129
Manual de AngularJS
Nota: Adems, tenemos ngChecked, aunque esta directiva no est en la documentacin del campo
checkbox, sino en otra pgina. https://docs.angularjs.org/api/ng/directive/ngChecked Viene a explicar
que sirve para conservar un valor en el atributo checked. Ese atributo en HTML funciona como un
boleano, si se encuentra el atributo se entiende que est chequeado y si no se encuentra checked es que
no debe estar marcado. Por ello los navegadores no estn obligados a memorizar ningn valor en el
checked. En esos casos puedes usar ngChecked. En definitiva, en la prctica ese campo sirve para
indicar una variable del scope donde se pueda deducir si el elemento debe estar o no marcado (checked).
Directiva ngModel
Si quieres usar un checkbox lo ms normal es que indiques la referencia de tu modelo donde quieres que se
guarde su estado.
<input type="checkbox" ng-model="vm.activo" />
A partir de este momento el checkbox est asociado a tu scope en vm.activo. Pero un detalle, en el scope
todava no est creada esa propiedad hasta que no pulses encima del checkbox para activarlo o desactivarlo.
En ese momento pasa a existir vm.activo en el modelo, aunque tambin si lo deseamos podemos
inicializarla en un controlador.
http://desarrolloweb.com/manuales/manual-angularjs.html
Pgina 54 de 129
Manual de AngularJS
vm.activo = true;
Como sabes, durante la vida de tu aplicacin, el estado del checkbox se traslada automticamente desde la
vista al modelo y desde el modelo a la vista, por el proceso conocido por "doble binding". En resumen, si
en cualquier momento desde el Javascript cambias el valor de vm.activo, siempre se actualizar la vista. Por
supuesto, si en la vista pulsas sobre el campo para activarlo o desactivarlo, en el modelo tambin quedar
reflejado el nuevo estado.
Directiva ngChange
Esta directiva sirve para especificar acciones cuando cambia el estado del checkbox. Pero atencin, porque
son solo cambios debidos a la interaccin con el usuario. Es decir, si mediante Javascript cambiamos el
modelo asociado a ese checkbox, cambindolo de un estado a otro no se activar el evento ng-change. La
vista seguir alterando el estado del campo, gracias al mencionado binding, pero la expresin que hayas
colocado en ng-change no se ejecutar.
<input type="checkbox" ng-change="vm.avisar()">
<p>
<input type="checkbox" ng-model="vm.activo" ng-change="vm.avisar()">
Este campo es vm.activo y su valor en el modelo es {{ vm.activo }}.
<br />
Tiene adems un ng-change asociado con el mtodo vm.avisar().
</p>
<p>
http://desarrolloweb.com/manuales/manual-angularjs.html
Pgina 55 de 129
Manual de AngularJS
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.24/angular.min.js"></script>
<script>
var app = angular.module("app", [])
app.controller("appCtrl", function(){
var vm = this;
//podramos inicializar valores del modelo
//vm.activo = false;
vm.avisar = function(){
console.log("cambi");
}
});
</script>
</body>
</html>
Observa que al iniciarse por primera vez la pgina los valores del modelo (definidos en los checkboxes con
ng-model) no estn inicializados. Por ello las expresiones donde se vuelcan estos datos no muestran valor
alguno. Luego, cuando cambias el estado de los checkboxes ya se empieza a ver el estado de los elementos.
Esta situacin podra cambiar solo con inicializar esas propiedades en el controlador. Lo hemos colocado en
el cdigo comentado para que se vea bien.
El otro detalle que igual no salta a la vista es la llamada a la funcin del modelo vm.avisar(), colocada en el
ng-change del primer checkbox, que no se llama cuando se cambia el estado del campo como consecuencia
del Javascript. Demostrar eso es el motivo de la existencia del botn.
Hay infinidad de prcticas con checkboxes. Con lo que has visto aqu seguramente sepas desempear
cualquier situacin.
Pgina 56 de 129
Manual de AngularJS
potencia.
La directiva ya la hemos usado en diversos ejemplos anteriormente, incluso tenemos un artculo anterior
donde se introdujeron algunos detalles bsicos de ng-repeat para empezar a usarla. Ahora queremos
profundizar un poco ms en otros usos que resultarn muy tiles para cualquier tipo de aplicacin web.
En la documentacin de la directiva ngRepeat encuentras muchos datos tiles, aqui te vamos a resumir
algunos y vamos a realizar un ejemplo que lo ponga todo en prctica.
Sintaxis ngRepeat
Nos tenemos que familiarizar primero con la sintaxis usada para especificar el comportamiento del bucle en
ngRepeat. Aunque ya lo hemos visto en cantidad de ejemplos, comencemos por repasar la sintaxis bsica.
<p ng-repeat="elem in elementos">
{{ elem }}
</p>
En la directiva indicamos el recorrido a una coleccin y la variable donde vamos a tener el elemento actual:
"elem in elementos". En este caso "elementos" es la coleccin que vamos a recorrer en el bucle y "elem" es
la variable donde vamos a tener el elemento actual en cada repeticin.
Pero eso no es lo nico que se puede marcar en esta directiva, tambin podremos especificar otras cosas,
colocando el caracter "|" (tubera / pipe) como separador.
ng-repeat="elem in elementos | filtros | ordenacion"
Tcnicamente podemos decir que dentro del HTML de tu repeticin tendrs un scope local, donde
encontrars el elemento actual sobre el que ests iterando, as como otras variables tiles que veremos
tambin, como $index que nos devuelve el ndice actual en el recorrido.
Filtrado en ngRepeat
El filtrado nos sirve para hacer una bsqueda dentro de los elementos de la coleccin que tenemos en un
array o en un objeto en nuestro modelo.
http://desarrolloweb.com/manuales/manual-angularjs.html
Pgina 57 de 129
Manual de AngularJS
Nota: Por supuesto, la coleccin est del lado del cliente completa y lo que hace el filter es simplemente
definir cules elementos de esa coleccin desean visualizarse en la repeticin. Osea, es un filtrado de
datos de los que ya disponemos, no un buscador que pueda buscar entre miles de elementos y solo
recibir unos pocos en el cliente. Cuando ests filtrando ya tienes esos elementos en la memoria de
Javascript en un array u objeto.
Se indica con la palabra filter, seguida por ":" y la cadena o variable donde est la cadena que nos sirve para
filtrar.
ng-repeat="cerveza in vm.cervezas | filter:'pale' "
Esto nos mostrar solo aquellas cervezas que tienen la palabra "pale" escrita por algn lado. Por supuesto,
en lugar de un literal de cadena para el filtrado, puedes usar una variable de tu modelo.
ng-repeat="cerveza in vm.cervezas | filter:vm.filtroCliente"
Ahora utilizars el contenido de la variable vm.filtroCliente para mostrar aquellos elementos que
corresponda.
En este caso ordenamos los elementos por el campo "name". Lgicamente debe de ser un atributo del
objeto que ests recorriendo en la coleccin. Luego opcionalmente colocamos un boleano para indicar el
orden. De manera predeterminada el orden es ascendente. Si el boleano es true, entonces el orden se hace
descendente y si es false, entonces es ascendente.
Nuevamente, el orden se indicar habitualmente a partir de variables de Javascript o del modelo de nuestra
vista. En un cdigo que podra ser como este:
ng-repeat="cerveza in vm.cervezas | orderBy:vm.campo:vm.orden"
Pgina 58 de 129
Manual de AngularJS
Por ejemplo en el scope actual tenemos la variable $index, que nos indica el ndice actual en la iteracin. El
primer ndice recuerda que es cero, el segundo ser uno, etc. Para mostrar ese ndice hacemos como con
cualquier otro dato que exista en el scope, meterlo dentro de una expresin encerrada con dobles llaves.
<p ng-repeat="elem in elementos">
El elemento actual es {{ $index }} y su valor es {{ elem }}
</p>
Junto con el $index, este es el conjunto de variables inyectadas automticamente en el scope local:
$index, numrcico. Es el ndice de la iteracin.
$first, boleano, tendr el valor true para el primer elemento de la iteracin.
$middle, boleano, ser true en los elementos que no sean primero o ltimo.
$last, boleano, solo ser true en el ltimo elemento.
$even, boleano, ser true en caso que ese elemento sea impar en la lista de repeticin.
$odd, boleano, ser true en caso que el elemento sea de ndice par.
http://desarrolloweb.com/manuales/manual-angularjs.html
Pgina 59 de 129
Manual de AngularJS
<br />
<button ng-click="vm.orden=true">Contrario</button>
</p>
<p>
<input type="radio" name="campo" ng-model="vm.campo" value="name"> Nombre
<br />
<input type="radio" name="campo" ng-model="vm.campo" value="description"> Descripcin
</p>
</aside>
<section>
<ul>
<li ng-repeat="cerveza in vm.cervezas | filter:vm.filtroCliente | orderBy:vm.campo:vm.orden" ng-class="{even: $even, odd: $odd}">
<span>{{$index +1}}.- {{cerveza.name}},</span> {{ cerveza.description }}
</li>
</ul>
</section>
</div>
Para el texto del filtrado usamos el INPUT type text que hemos marcado con ng-model="vm.filtroCliente".
Para el orden tenemos dos tipos de controles, diferentes para poder practicar con ms cosas. Tenemos un
par de botones que nos permiten marcar orden alfabtico o contrario, que tienen sus correspondientes ngclick para definir comportamientos. Por otra parte tenemos un par de campos INPUT de radio para definir
si queremos que se ordene por el nombre de la cerveza o su campo descripcin.
Pero sobre todo te tienes que fijar en el listado de cervezas que realizamos con una lista UL y sus
correspondientes LI. Echa un vistazo a la directiva y al template que engloba:
<li ng-repeat="cerveza in vm.cervezas | filter:vm.filtroCliente | orderBy:vm.campo:vm.orden" ng-class="{even: $even, odd: $odd}">
<span>{{$index +1}}.- {{cerveza.name}},</span> {{ cerveza.description }}
</li>
Pgina 60 de 129
Manual de AngularJS
vm.orden = false;
vm.campo = "name";
Realmente en este Javascript hay poco que necesites aprender, que no hayas visto ya en artculos anteriores.
Te podr interesar la inicializacin de datos en el scope qe encuentras en las primeras lneas de la funcin
del controlador.
Aunque para la materia que nos trata no importa demasiado, s que necesitars unos estilos CSS para
formatear un poco la presentacin de ese HTML, de manera que quede bonito y puedas apreciar algunas
cosas como los colores de fondo de tipo cebra para los elementos de la lista.
body{ font-family: sans-serif;}
li{
font-size: 0.8em;
margin-bottom: 10px;
padding: 10px;
}
li span{
font-weight: bold;
display: block;
font-size: 1.2em;
}
aside{
width: 200px;
float: right;
http://desarrolloweb.com/manuales/manual-angularjs.html
Pgina 61 de 129
Manual de AngularJS
padding: 20px;
display: table-cell;
}
aside h2{
margin-bottom: 3px;
}
section{
display: table-cell;
}
li.even{
background-color: #d5d5d5;
}
li.odd{
background-color: #d5d5ff;
}
Eso es todo de momento, espero que puedas aprovechar ya mismo algunas de estas potentes caractersticas
de ngRepeat. Como habrs encontrado, esta directiva permite hacer cosas impactantes sin escribir nada de
cdigo, algo que apreciars sobre todo si tienes algo de experiencia en Javascript o libreras como jQuery.
Pero OJO, esa misma potencia puede que resulte perjudicial para tu aplicacin si se usa sin control, nunca
intentes usar ng-repeat con conjuntos masivos de datos, a lo sumo con elementos de 100 en 100, aplicando
tcnicas como la paginacin para reducir los elementos en la vista.
http://desarrolloweb.com/manuales/manual-angularjs.html
Pgina 62 de 129
Manual de AngularJS
Ajax en Angular
Introduccin a los mecanismos para realizar conexiones con el servidor asncronas por HTTP con
AngularJS. Lo que comnmente conocemos por Ajax, con ejemplos que nos facilitarn entender una de las
facetas ms potentes de este frameweork Javascript y el desarrollo frontend basado en las cada vez ms
populares API REST.
Service $http
El servicio $http (service en ingls, tal como se conoce en AngularJS) es una funcionalidad que forma parte
del ncleo de Angular. Sirve para realizar comunicaciones con servidores, por medio de HTTP, a travs de
Ajax y va el objeto XMLHttpRequest nativo de Javascript o va JSONP.
Despus de esa denominacin formal, que encontramos en la documentacin de AngularJS, te debes de
quedar por ahora en que nos sirve para realizar solicitudes y para ello el servicio $http tiene varios tipos de
acciones posibles. Todos los puedes invocar a travs de los parmetros de la funcin $http y adems existen
varios mtodos alternativos (atajos o shortcuts) que sirven para hacer cosas ms especficas.
Entre los shortcuts encuentras:
http://desarrolloweb.com/manuales/manual-angularjs.html
Pgina 63 de 129
Manual de AngularJS
Nota: Si vienes de jQuery ya habrs podido experimentar las promesas "promise" en las llamadas a la
funcin $.ajax, $.get, $post, etc. En AngularJS funciona de manera muy similar.
El service $http es bastante complejo y tiene muchas cosas para aportar soluciones a las ms variadas
necesidades de solicitudes HTTP asncronas. De momento nos vamos a centrar en lo ms bsico que ser
suficiente para realizar un ejemplo interesante.
Como puedes ver, en la funcin de nuestro controlador, llamada controladorPrincipal, le estamos indicando
que recibir un parmetro donde tiene que inyectar el service $http.
Al declarar la funcin recibirs esa dependencia como parmetro.
function controladorPrincipal($http){
Ahora, dentro del cdigo de ese controlador podrs acceder al servicio $http para realizar tus llamadas a
Ajax.
Lo interesante es lo que nos devuelve este mtodo, que es un objeto "HttpPromise", sobre el cual podemos
operar para especificar el comportamiento de nuestra aplicacin ante diversas situaciones.
http://desarrolloweb.com/manuales/manual-angularjs.html
Pgina 64 de 129
Manual de AngularJS
Como puedes ver en este cdigo es que $http nos devuelve un objeto. Sobre ese objeto invocamos el
mtodo success() que sirve para indicarle la funcin que tenemos que ejecutar en caso de xito en la
solicitud Ajax. Esa funcin a su vez recibe un parmetro que es la respuesta que nos ha devuelto el servidor.
Nota: En Angualar 1.4 cambiaron el estndar de respuesta en caso de xito o fracaso de la conexin
Ajax. El nuevo mecanismo es bastante parecido, con funciones callback que se cargan a partir del
mtodo then(). Lo tienes descrito con ejemplos en el artculo de Estndar del patrn promise para los
mtodos del servicio $http en Angular 1.4.
Nota: Vamos a usar un API llamada REST Countries, que puedes encontrar en
http://restcountries.eu/
Este API nos devuelve JSON con datos sobre los pases del mundo. En principio puedes hacer diversas
operaciones con los comandos sobre el API, pero vamos a ver solamente unas pocas que nos permiten
recibir los datos de los pases agrupados por regiones.
Las URL que usaremos para conectarnos al API son como estas:
http://restcountries.eu/rest/v1/region/africa http://restcountries.eu/rest/v1/region/europe
Puedes abrirlas en tu navegador y observar cmo la respuesta es un conjunto de datos en notacin
JSON.
Aunque sencilla, esta aplicacin ya contene varias cosillas que para una mejor comprensin conviene ver
por separado.
Este es nuestro HTML:
<div ng-app="apiApp" ng-controller="apiAppCtrl as vm">
http://desarrolloweb.com/manuales/manual-angularjs.html
Pgina 65 de 129
Manual de AngularJS
<h1>Pruebo Ajax</h1>
<p>
Selecciona:
<select ng-model="vm.url" ng-change="vm.buscaEnRegion()">
<option value="http://restcountries.eu/rest/v1/region/africa">Africa</option>
<option value="http://restcountries.eu/rest/v1/region/europe">Europa</option>
<option value="http://restcountries.eu/rest/v1/region/americas">America</option>
</select>
</p>
<ul>
<li ng-repeat="pais in vm.paises">
Pas: <span>{{pais.name}}</span>, capital: {{pais.capital}}
</li>
</ul>
</div>
Puedes fijarte que tenemos un campo SELECT que nos permite seleccionar una regin y para cada uno de
los OPTION tenemos como value la URL del API REST que usaramos para obtener los pases de esa
regin.
Aprecia que en el campo SELECT est colocada la directiva ngChange, que se activa cuando cambia el
valor seleccionado en el combo. En ese caso se hace una llamada a un mtodo llamado buscaEnRegion()
que veremos luego escrito en nuestro controlador.
Tambin encontrars una lista UL en la que tienes una serie de elementos LI. Esos elementos LI tienen la
directiva ngRepeat para iterar sobre un conjunto de pases, de modo que tengas un elemento de lista por
cada pas.
Ahora puedes fijarte en el Javascript:
angular
.module('apiApp', [])
.controller('apiAppCtrl', ['$http', controladorPrincipal]);
function controladorPrincipal($http){
var vm=this;
vm.buscaEnRegion = function(){
$http.get(vm.url).success(function(respuesta){
//console.log("res:", respuesta);
vm.paises = respuesta;
});
}
}
Creamos un module y luego un controlador al que inyectamos el $http como se explic al inicio del artculo.
Luego, en la funcin que construye el controlador, tenemos un mtodo que se llama buscaEnRegion() que
es el que se invoca al modificar el valor del SELECT. Ese mtodo es el que contiene la llamada Ajax.
http://desarrolloweb.com/manuales/manual-angularjs.html
Pgina 66 de 129
Manual de AngularJS
Usamos el shortcut $http.get() pasando como parmetro la URL, que sacamos del value que hay marcado
en el campo SELECT del HTML. Luego se especifica una funcin para el caso "success" con el patrn
"promise". Esa funcin devuelve en el parmetro "respuesta" aquello que nos entreg el API REST, que es
un JSON con los datos de los pases de una regin. En nuestro ejemplo, en caso de xito, simplemente
volcamos en un dato del modelo, en el "scope", el contenido de la respuesta.
En concreto ves que la respuesta se vuelca en la variable vm.paises, que es justamente la coleccin por la
que se itera en el ng-repeat de nuestro HTML.
http://desarrolloweb.com/manuales/manual-angularjs.html
Pgina 67 de 129
Manual de AngularJS
<ul>
<li ng-repeat="pais in vm.paises">Pas: <span>{{pais.name}}</span>, capital: {{pais.capital}}</li>
</ul>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.24/angular.min.js"></script>
<script>
angular
.module('apiApp', [])
.controller('apiAppCtrl', ['$http', controladorPrincipal]);
function controladorPrincipal($http){
var vm=this;
vm.buscaEnRegion = function(){
$http.get(vm.url).success(function(respuesta){
//console.log("res:", respuesta);
vm.paises = respuesta;
});
}
}
</script>
</body>
</html>
En el siguiente artculo explicaremos cmo acceder por Ajax a un JSON pero con JSONP.
JSONP en AngularJS
Ejercicio Ajax en el que realizamos un acceso a API REST que devuelve informacin mediante
JSONP, realizado con el service $http de AngularJS.
JSONP es un mecanismo muy til cuando estamos trabajando con Ajax en Javascript y queremos traernos
datos que residen en otro servidor. Existe una problemtica por la cual no puedes cargar datos con
Javascript que te vengan desde servidores de otros dominios, pues puede darte un error de seguridad si es
que el servidor al que te conectas no est configurado para aceptar solicitudes "cross domain".
Ahora no buscamos tanto introducir esta variante de JSON, pues ya la vimos con detalle en el artculo
dedicado a JSONP. Simplemente te queremos explicar cmo debes usar JSONP dentro de AngularJS de
una manera muy sencilla. Es un excelente ejercicio para practicar con todo lo que llevamos visto en el
Manual de AngularJS.
http://desarrolloweb.com/manuales/manual-angularjs.html
Pgina 68 de 129
Manual de AngularJS
Nota: En el artculo dedicado a Ajax en AngularJS explicamos ms detalles de este "service" ofrecido
por AngularJS.
Nota: Esa funcin callback es la que usamos en Javascript del navegador para restaurar los datos del
JSONP. Como decimos es algo que realmente no necesitas preocuparte mucho, pues es transparente
para ti. Si quieres obtener ms informacin podras consultar el artculo sobre JSONP.
http://example.com/url.json?callback=JSON_CALLBACK
http://desarrolloweb.com/manuales/manual-angularjs.html
Pgina 69 de 129
Manual de AngularJS
Ejemplo realizado en AngularJS para traer datos de API REST con JSONP
Ahora vamos a realizar un ejemplo en AngularJS para practicar lo aprendido. De este modo vers que es
todo muy sencillo. En este ejemplo traemos datos de cervezas de un API REST pblica llamada "Open
Beer Database". Los datos los obtenemos por JSONP y puedes ver un ejemplo de conexin y cdigo en
esta pgina de la documentacin del API.
http://openbeerdatabase.com/documentation/examples-jsonp
En nuestro caso concreto accedemos a cervezas en vez de cerveceras, pero el ejemplo es bien similar.
Nuestra URL para obtener datos del API es como esta:
http://api.openbeerdatabase.com/v1/beers.json?callback=JSON_CALLBACK&query=ale
Como puedes ver, en la URL indicamos en el parmetro "callback" el nombre de la funcin callback que
nos pide Angular. Adems hay un segundo parmetro llamado "query" con el que podemos expresar unas
palabras clave para hacer bsquedas de cervezas que contengan esas palabras.
Sabiendo esto, ahora pasemos a ver nuestro cdigo. Esta es la parte del HTML.
<div ng-app="apiApp" ng-controller="apiAppCtrl as vm">
<h1>Pruebo Ajax con JSONP</h1>
<p>
Busca cerveza:
<input type="text" ng-model="vm.nombre"> <input type="button" value="Buscar" ng-click="vm.buscaCervezas()">
</p>
<ul>
<li ng-repeat="cerveza in vm.cervezas"><span>{{cerveza.name}},</span> {{ cerveza.description }}</li>
</ul>
</div>
Como ves, tenemos un campo de texto donde podemos escribir un dato y un botn de buscar. Al darle a
buscar llamamos a un mtodo de nuestro "scope" para traernos las cervezas que tengan el texto escrito en el
campo de texto, ya sea en su nombre o descripcin.
Luego tenemos un bucle definido con ng-repeat en el que recorremos una coleccin de cervezas.
Ahora puedes ver la parte del Javascript:
angular
.module('apiApp', [])
.controller('apiAppCtrl', controladorPrincipal);
vm.buscaCervezas = function(){
var url = "http://api.openbeerdatabase.com/v1/beers.json?callback=JSON_CALLBACK";
if(vm.nombre){
url += "&query=" + vm.nombre;
http://desarrolloweb.com/manuales/manual-angularjs.html
Pgina 70 de 129
Manual de AngularJS
}
$http.jsonp(url).success(function(respuesta){
console.log("res:", respuesta);
vm.cervezas = respuesta.beers;
});
}
}
Bien, supongo que estos cdigos ya te irn sonando y en concreto este ejercicio es muy parecido al anterior
en el que conocimos Ajax. En la parte importante, nuestro controlador, apreciars que tenemos un mtodo
llamado buscaCervezas() que es el que se encarga de hacer todo el trabajo.
En ese mtodo primero construimos la URL para acceder al API, agregndole el nombre de la cerveza que
quieres buscar.
Luego accedemos por medio de $http.jsonp() a la URL construida y definimos una funcin que se ejecutar
en caso de xito de la conexin Ajax (success). en esa funcin simplemente volcamos las cervezas
encontradas en el scope, con lo que se actualiza automticamente la vista en el bloque donde tenamos la
directiva ng-repeat de nuestro HTML.
Con esto es todo. Solo te queda practicar lo aprendido por tu cuenta para no dejarte un detalle sobre las
conexiones JSONP en AngularJS.
http://desarrolloweb.com/manuales/manual-angularjs.html
Pgina 71 de 129
Manual de AngularJS
Como ves, la primera direccin es la URL relativa donde enviar los datos (tambin podra ser absoluta) y el
segundo parmetro son los datos que queremos enviar al destino.
Este mtodo devuelve como resultado un objeto sobre el que podemos implementar con el patrn promesa
algunas operaciones en diversas situaciones con respecto a esa conexin con el servidor, algo que ya viste en
lo ejemplos de Ajax anteriores. Lo que vamos a aprender de momento es realizar acciones en caso de xito
y para ello tenemos que indicarlas con una funcin en "success".
var conAjax = $http.post("recibe.php", {uno: 1, fruta: "manzana"});
conAjax.success(function(respuesta){
console.log(respuesta);
});
En la funcin que asociamos al caso success, como ya habrs visto muchas veces, recibimos un parmetro
con la respuesta que nos devuelve el servidor. En este caso simplemente la volcamos a la consola de
Javascript.
Nota: Este cdigo lo encontrars habitualmente encadenando llamadas, sin necesidad de declarar la
variable "conAjax". Luego haremos ejemplos que usen esa comn forma de codificar.
Nota: Para que nos entendamos, en un lenguaje como PHP, cuando enviamos datos por post los
recoges con el array $_POST. Ese array no aceptara diversos niveles de anidacin para recibir datos
complejos, osea, podemos tener claves con valores simples. Pero se nos queda un poco corto para
aplicaciones modernas. En PHP si accedes a $_POST encontrars que el array est vaco.
http://desarrolloweb.com/manuales/manual-angularjs.html
Pgina 72 de 129
Manual de AngularJS
Este asunto de los niveles de anidacin en los datos que se envan con JSON se ve por ejemplo en este
cdigo, perfectamente vlido y habitual.
$http.post("recibe2.php", {
nombre: "Miguel",
fechaNacimiento: "21/02/1975",
sitiosPreferidos: [
"DesarrolloWeb.com",
"Guiarte.com"
],
direccion: {
calle: "De la alegra",
numero: 18,
ciudad: "Villadigital"
}
})
.success(function(respuesta){
console.log(respuesta);
});
Ese objeto complejo JSON lo recibirs en el servidor tal cual. El cdigo para recogerlo depender de tu
lenguaje de servidor. Por ejemplo en PHP lo hara de esta manera:
file_get_contents("php://input")
Eso nos devolvera una cadena de texto, que si quieres volcar a un objeto nativo de PHP usars la funcin
json_decode(). Tu cdigo podra quedarte parecido a este:
$objDatos = json_decode(file_get_contents("php://input"));
A partir de ese momento encontrars que puedes acceder a los datos del JSON recibido como ests
acostumbrado en el trabajo con objetos PHP.
echo $objDatos->nombre;
echo $objDatos->sitiosPreferidos[0];
echo $objDatos->direccion->calle;
http://desarrolloweb.com/manuales/manual-angularjs.html
Pgina 73 de 129
Manual de AngularJS
Observa que en ng-model hemos volcado los campos del formulario dentro de un objeto llamado "fdatos".
Osea, en el modelo de la vista "vm" tenemos un objeto "datosf" y dentro ya encontraremos los datos de
nuestro formulario.
Tambin repara en la directiva ngSubmit que hemos colocado en la etiqueta FORM. Vers que la hemos
asociado con una funcin de nuestro modelo: vm.enviar(). En esa funcin que veremos a continuacin es
donde debes escribir el cdigo para poder enviar el formulario.
Nota: Esto no ests obligado a hacerlo as necesariamente, porque puedes crear la estructura que desees
en el modelo. Simplemente nos resultar ms cmodo colocar directamente los datos vinculados a un
objeto de datos del formulario. Al servidor por post no vamos a enviar todo el modelo de la vista, sino
nicamente los datos del formulario. Como esta estructura ya nos permite tener los datos del formulario
en un objeto independiente, nos ahorrar el tener que hacerlo "a mano". Enseguida lo vers mejor.
Para que esto funcione en tu Javascript debes inicializar "fdatos" como un objeto, aunque sea vaco. Por ello
en tu controller deberas incluir este cdigo.
vm.fdatos = {};
Es un cdigo parcial, luego lo vers en el contexto del controlador completo. Observa que en tu "vm" has
inicializado el objeto "fdatos" con un literal de objeto vaco, expresado con las dos llaves.
Esto ya nos deja en muy buena situacin para enviar ese formulario de una manera muy limpia. Ahora te
mostramos el cdigo completo para crear nuestro controlador.
angular
.module('app', [])
.controller('appCtrl', ['$http', controladorPrincipal]);
function controladorPrincipal($http){
var vm=this;
http://desarrolloweb.com/manuales/manual-angularjs.html
Pgina 74 de 129
Manual de AngularJS
Con esto creo que lo tendrs todo claro para poder enviar datos a un servidor por medio de post, datos que
podrn ser todo lo complejos que necesites en tu aplicacin. Como puedes comprobar la llamada a
$http.post() te hace todo el trabajo de la solicitud HTTP por medio de Ajax, por lo que solo tendrs que
programar el comportamiento especfico para tus necesidades, tanto en el cliente como en el servidor.
Nota: a pesar que los mtodos success() y error() estn obsoletos (deprecated) siguen funcionando, para
asegurar que no da errores el cdigo creado para versiones anteriores de AngularJS. Son considerados
como "legacy methods" y no conviene usarlos porque en un futuro se dejar de dar soporte.
http://desarrolloweb.com/manuales/manual-angularjs.html
Pgina 75 de 129
Manual de AngularJS
= $http.get("https://restcountries.eu/rest/v1/all");
Aunque en seguida veremos que generalmente el objeto no es necesario guardarlo en una variable, sino
encadenar directamente la configuracin del "promise".
Mtodo then()
Sobre el objeto promesa podemos invocar el mtodo then(). ste nos permite definir dos funciones con las
cuales podremos indicar las acciones a realizar, tanto para el caso de suceso en la solicitud como para el caso
de error.
Lo comn sera utilizar un sistema de encadenamiento de mtodos, que nos permita recibir el objeto
promesa y a continuacin invocar su mtodo then() para realizar las acciones oportunas cuando se reciba la
respuesta del servidor.
$http.get("http://example.com/url/ajax")
.then(function(res){
// acciones a realizar cuando se recibe respuesta con xito
}, function(res){
// acciones a realizar cuando se recibe una respuesta de error
});
Cmo has podido apreciar, el mtodo then() recibe dos parmetros que configuramos con dos funciones
annimas. La primera de las funciones sirve para indicar las acciones que quieres realizar cuando recibes del
servidor una respuesta con xito, es decir, una respuesta con un estatus del protocolo HTTP que considere
como "todo correcto", status 200 por ejemplo. La segunda de las funciones sirve para indicar las acciones
que se quiere realizar al recibir una respuesta de error, con un estatus tal qu 404, de pgina no encontrada,
o 500, de error de ejecucin del servidor, etc.
http://desarrolloweb.com/manuales/manual-angularjs.html
Pgina 76 de 129
Manual de AngularJS
Como novedad, las funciones annimas que asignamos al mtodo then(), reciben un objeto respuesta.
.then(function(res){
Este objeto tiene una serie de atributos con los datos de la respuesta que hemos recibido del servidor. Por
ejemplo podremos encontrar el atributo "data", que nos devolvera el objeto nativo de Javascript creado a
partir del JSON que se recibe en el cuerpo del response. Tambin podremos encontrar por ejemplo un
atributo "status" con el valor exacto del status de respuesta, 200, 404 o el que sea.
Para observar ese nuevo objeto respuesta te recomiendo hacer un console.log() y as podrs apreciar todos
los atributos que nos entrega Angular para indicarnos exactamente cmo ha ido la solicitud Ajax. No
obstante ahora vamos a poner un pequeo ejemplo donde podrs ver cmo podremos utilizar este objeto
de respuesta para producir una salida adecuada es una solicitud Ajax con angularjs.
<script src="../angular.min.js"></script>
<script src="paisesApp.js"></script>
</body>
</html>
http://desarrolloweb.com/manuales/manual-angularjs.html
Pgina 77 de 129
Manual de AngularJS
Ahora vamos a mostrar el cdigo JavaScript de nuestro "Module". Apreciars que tienes un controlador que
es donde realizamos la solicitud Ajax para poblar array de pases con el que realizar el listado en la pgina.
angular
.module("paisesApp", [])
.controller("PaisesAppController", ["$scope", "$http", function($scope, $http){
$scope.paises = [];
$http.get("https://restcountries.eu/rest/v1/all")
.then(function(res){
$scope.paises = res.data;
}, function(res){
$scope.paises = [{name: "Error!! " + res.status}];
});
}]);
Fjate en la primera funcin annima que enviamos al mtodo then(), cmo hacemos uso del atributo data
de la respuesta para asignarlo al array de pases del scope.
La segunda funcin annima indicada en caso de error utiliza la respuesta para extraer el estatus recibido
(atributo status). No sera la mejor manera de mostrar un error pero nos sirve como alternativa para este
pequeo ejemplo.
Conclusin
Con esto terminamos este ejercicio en el cual hemos visto el nuevo estndar de promesas para solicitudes
Ajax que utilizamos en las ltimas versiones de angularjs. La verdad es que no tiene ninguna dificultad por
lo que entendemos que no hace falta mucha ms explicacin para poder empezar a usarlo y adaptarnos API
de las nuevas versiones de este framework Javascript.
Pgina 78 de 129
Manual de AngularJS
Para poder ser tan rpidos usaremos un sencillo archivo JSON como fuente de datos, donde podremos
generar nuestro modelo de datos, con distintas entidades, y datos de prueba. Como servidor REST
usaremos un programa llamado "json-server", desarrollado con NodeJS que nos ofrece la posibilidad de
tener un servidor web que responde a las operaciones tpicas de las API.
El API REST que vamos a crear ser perfectamente funcional, es decir, realizar todas las operaciones
posibles sobre nuestros datos (lecturas, modificaciones, inserciones y borrados), almacenando los datos en
el archivo JSON. La persistencia de los datos se realiza en el propio archivo de texto JSON, de este modo,
en futuros accesos a la aplicacin web, el API recordar su estado manteniendo toda la actividad que se haya
realizado a lo largo del tiempo.
Al final del artculo vers adems un vdeo donde se explica todo el proceso y se muestra cmo realizarlo en
pocos minutos.
Nota: Si no tienes claro lo que es REST te recomiendo que te leas el artculo Qu es REST de Eduard
Toms que lo explica muy bien y muy rpido. Incluso si tienes una idea de lo que es un API REST y
quieres completar la informacin y saber ms detalles de este tipo de recursos, la lectura te vendr muy
bien.
Descargar json-server
El primer paso para tener nuestra API es descargar e instalar json-server. Este programa es un paquete de
NodeJS que instalaremos va npm.
http://desarrolloweb.com/manuales/manual-angularjs.html
Pgina 79 de 129
Manual de AngularJS
El gestor de paquetes npm nos instalar json-server con todas sus dependencias. Mientras tanto, podemos ir
realizando el siguiente paso.
Nota: Puedes saber algo ms de JSON en este artculo. En realidad no es ms un archivo de texto
plano, que guardars con codificacin UTF-8. La notacin para definir los datos la realizamos como si
fuera un objeto Javascript. Al trabajar con JSON no se realiza una definicin del modelo de datos como
se hace en una base de datos relacional, ya que este modelo de datos se define a travs de los propios
datos.
Podemos ver un juego de datos de muestra, en el siguiente cdigo JSON, que almacena pelculas y un
conjunto de clasificaciones de pelculas.
{
"peliculas": [
{
"id": 1,
"nombre": "El sexto sentido",
"director": "M. Night Shyamalan",
"clasificacion": "Drama"
},
{
"id": 2,
"nombre": "Pulp Fiction",
"director": "Tarantino",
"clasificacion": "Accin"
},
{
"id": 3,
"nombre": "Todo Sobre Mi Madre",
"director": "Almodobar",
"clasificacion": "Drama"
},
{
"id": 4,
"nombre": "300",
"director": "Zack Snyder",
"clasificacion": "Accin"
},
{
"id": 5,
"nombre": "El silencio de los corderos",
"director": "Jonathan Demme",
"clasificacion": "Drama"
http://desarrolloweb.com/manuales/manual-angularjs.html
Pgina 80 de 129
Manual de AngularJS
},
{
"id": 6,
"nombre": "Forrest Gump",
"director": "Robert Zemeckis",
"clasificacion": "Comedia"
},
{
"id": 7,
"nombre": "Las Hurdes",
"director": "Luis Buuel",
"clasificacion": "Documental"
}
],
"clasificaciones": [
{
"nombre": "Drama",
"id": 1
},
{
"nombre": "Comedia",
"id": 2
},
{
"nombre": "Documental",
"id": 3
},
{
"nombre": "Accin",
"id": 4
}
]
}
Este archivo JSON tendr tpicamente una extensin .json. En nuestro caso lo podramos guardar como
"peliculas.json".
Enseguida veremos que nos aparece una serie de mensajes indicando cmo podramos acceder a nuestro
origen de datos, a travs de las URL del servidor, o las URL de los recursos o entidades generadas en el
JSON.
http://desarrolloweb.com/manuales/manual-angularjs.html
Pgina 81 de 129
Manual de AngularJS
Acceder al API
Ahora ya solo nos queda acceder al API. Realmente podrs entrar en la "home" del servidor json-server
para tu API a travs de una URL como esta:
http://localhost:3000
En esa pgina encontrars enlaces a los distintos recursos de tu API. Si los abres vers que te devuelve datos
JSON como la mayora de las API REST. Las operaciones que podrs realizar sobre el API son las tpicas y
se opera bsicamente mediante los verbos del HTTP. Realmente aqu no difiere en nada de cualquier otro
API que puedas usar.
Adems, el API est perfectamente habilitada para invocarla desde otros dominios gracias a tener habilitado
CORS, o si se desea usando JSONP.
En resumen, en menos de 5 minutos tenemos un API funcionando que nos vendr perfecto para realizar
nuestra programacin Javascript del lado del cliente con acceso a datos de un API. Como hemos dicho, este
servidor de JSON est ms enfocado a fines didcticos o tambin al prototipado de un proyecto web o App
para mviles.
Objeto de estudio aparte sera el acceso a esos datos, que generalmente hars con Ajax, usando un
framework como AngularJS o una librera como BackboneJS, o al menos con jQuery.
Para ver este vdeo es necesario visitar el artculo original en: http://desarrolloweb.com/articulos/crearapi-rest-json-server.html
http://desarrolloweb.com/manuales/manual-angularjs.html
Pgina 82 de 129
Manual de AngularJS
Este artculo es obra de Miguel Angel Alvarez
Fue publicado por primera vez en 27/11/2015
Disponible online en http://desarrolloweb.com/articulos/crear-api-rest-json-server.html
http://desarrolloweb.com/manuales/manual-angularjs.html
Pgina 83 de 129
Manual de AngularJS
Pues bien, podemos tener ambas cosas. Una aplicacin de una sola pgina, pero que es capaz de representar
URL distintas, simulando lo que sera una navegacin a travs de la aplicacin, pero sin salirnos nunca de la
pgina inicial. Esto nos sirve para varias cosas, entre otras:
Memorizar rutas profundas dentro de nuestra aplicacin. Podemos contar con enlaces que nos
lleven a partes internas (deeplinks), de modo que no estemos obligados a entrar en la aplicacin a
travs de la pantalla inicial.
Eso facilita tambin el uso natural del sistema de favoritos (o marcadores) del navegador,
http://desarrolloweb.com/manuales/manual-angularjs.html
Pgina 84 de 129
Manual de AngularJS
as como el historial. Es decir, gracias a las rutas internas, seremos capaces de guardar en favoritos
un estado determinado de la aplicacin. A travs del uso del historial del navegador, para ir hacia
delante y atrs en las pginas, podremos navegar entre pantallas de la aplicacin con los botones del
navegador.
Mantener vistas en archivos independientes, lo que reduce su complejidad y administrar los
controladores que van a facilitar el procesamiento dentro de ellas.
Nota: ste es el comportamiento de cualquier navegador, no estamos apuntando nada que tenga que
ver con Javascript o con AngularJS. Angular, as como otros frameworks Javascript MVC se aprovechan
de esta caracterstica para implementar el sistema de enrutado.
En el caso de AngularJS no habr un movimiento de scroll, pues con Javascript se detectar el cambio de
ruta en la barra de direcciones para intercambiar la vista que se est mostrando.
Por ello, volviendo a la pregunta de antes: "si la posibilidad de crear varias rutas dentro de una aplicacin
contradice el sistema de Single Page Application", observamos que realmente no son pginas distintas, sino
que es la misma pgina. Lo que estamos haciendo es "simular" la navegacin por varias URL cuando
realmente es la misma, con enlaces internos.
Instalar ngRoute
El mdulo ("module" en la terminologa anglosajona de Angular) ngRoute es un potente paquete de
utilidades para configurar el enrutado y asociar cada ruta a una vista y un controlador, tal como hemos
dicho. Sin embargo este mdulo no est incluido en la distribucin de base de Angular, sino que en caso de
pretender usarlo tenemos que instalarlo y luego inyectarlo como dependencia en el mdulo principal de
nuestra aplicacin.
http://desarrolloweb.com/manuales/manual-angularjs.html
Pgina 85 de 129
Manual de AngularJS
Como no lo tenemos en el script bsico de Angular, debemos instalarlo "a mano". lo conseguimos
incluyendo el script del cdigo Javascript del mdulo ngRoute.
<script src="angular-route.js"></script>
Nota: Ojo que esta ruta no debes copiar y pegarla tal cual. Muchas veces usars el CDN
correspondiente y debers asegurarte de estar usando en el mdulo ngRoute de la misma versin de
AngularJS que cargaste inicialmente. Otro detalle es que este script lo tienes que incluir despus de haber
incluido el script del core de AngularJS.
Inyeccin de dependencias
El segundo paso sera inyectar la dependencia con ngRoute en el mdulo general de nuestra aplicacin. Esto
lo hacemos en la llamada al mtodo module() con el que iniciamos cualquier programa AngularJS, indicando
el nombre de las dependencias a inyectar en un array.
angular.module("app", ["ngRoute"])
Hasta ahora este array de dependencias, cuando llambamos a angular.module(), estaba siempre vaco. A
medida que se compliquen nuestras aplicaciones podremos necesitar inyectar ms cosas. Por ejemplo, las
directivas creadas por terceros desarrolladores tambin las inyectars de esta manera en tu mdulo principal
de la aplicacin. Eso lo veremos ms adelante.
Las rutas las configuras por medio del mtodo when() que recibe dos parmetros. Por un lado la ruta que se
est configurando y por otro lado un objeto que tendr los valores asociados a esa ruta. De momento
http://desarrolloweb.com/manuales/manual-angularjs.html
Pgina 86 de 129
Manual de AngularJS
vamos a conocer solo stos que seran los fundamentales para empezar.
"controller", para indicar el controlador
"controllerAs", el nombre con el que se conocer el scope dentro de esa plantilla
"templateUrl", el nombre del archivo, o ruta, donde se encuentra el HTML de la vista que se debe
cargar cuando se acceda a la ruta.
Podemos ver un ejemplo completo de configuracin de rutas.
angular.module("app", ["ngRoute"])
.config(function($routeProvider){
$routeProvider
.when("/", {
controller: "appCtrl",
controllerAs: "vm",
templateUrl: "home.html"
})
.when("/descargas", {
controller: "appCtrl",
controllerAs: "vm",
templateUrl: "descargas.html"
})
.when("/opciones", {
controller: "appCtrl",
controllerAs: "vm",
templateUrl: "opciones.html"
});
})
.controller("appCtrl", function(){
//cdigo del controlador (lo estoy usando en todas las rutas, en este sencillo ejemplo)
});
Hemos encadenado varias llamadas a mtodos when() sobre el $routeProvider, para definir cada una de las
rutas que tendremos en nuestra pequea aplicacin.
Nota: Observa que en cada una de las rutas tenemos definido el mismo controlador. Esto no tiene por
qu ser as, podras perfectamente tener un controlador distinto para cada ruta del sistema.
Para finalizar, podemos ver el cdigo HTML de una pgina donde usaramos estas rutas.
<body ng-app="app">
<nav>
<ul>
<li><a href="#/">Datos personales</a></li>
<li><a href="#/descargas">Descargas</a></li>
<li><a href="#/opciones">Opciones de cuenta</a></li>
http://desarrolloweb.com/manuales/manual-angularjs.html
Pgina 87 de 129
Manual de AngularJS
</ul>
</nav>
<hr />
<div ng-view></div>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.24/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.24/angular-route.js"></script>
<script src="app.js"></script>
</body>
Echa un vistazo a los enlaces que hay dentro de la etiqueta NAV. Esos son los enlaces que provocaran la
navegacin en el enrutado definido en la anterior configuracin. Observars que los href de los enlaces
estn asociados a las mismas rutas definidas en el $routeProvider. Por tanto, pulsando cada enlace Angular
nos mostrar la vista indicada en la declaracin que hemos mostrando antes en el config() del
$routeProvider.
Tienes tambin que fijarte en la divisin DIV que hay ms abajo que tiene la directiva ngView. En principio
no necesitas indicar ms cosas como valor de esa directiva. AngularJS ya sabe que las vistas las debe
desplegar en ese contenedor.
Solo a modo de curiosidad, fjate que en el HTML no hemos definido ningn controlador, osea, no est la
directiva ng-controller por ninguna parte. Sin embargo, en las vistas internas s que se est asociando un
controlador, porque se ha declarado en el $routeProvider.
Nota: No queremos adelantarnos, pero si se te ocurre jugar con este prototipo y creas un poco de
funcionalidad en el controlador que estamos usando en las vistas comprobars que los datos se
inicializan cada vez que accedemos a las vistas de nuevo. Esto lo explicaremos ms adelante, as que no
te preocupes si no has entendido todava a qu nos estamos refiriendo.
Vistas independientes
Para acabar solo queda comentar el cdigo de las vistas independientes. Tal como se defini en el
$routeProvider, existe un cdigo para cada una de las vistas, alojado en archivos HTML independientes. La
vista alojada en "/" se llama "home.html", la vista de la ruta "/descargas" est en el archivo
"descargas.html", etc. Esos archivos estn en el mismo directorio que la vista principal, pero realmente
podran estar en cualquier otra ruta que especifiquemos.
El cdigo que coloques en las vistas es indiferente. Simplemente pondrs HTML, directivas y todo lo que
venimos usando hasta el momento en las vistas. Escribe el HTML que gustes, de momento no tiene ms
importancia.
http://desarrolloweb.com/manuales/manual-angularjs.html
Pgina 88 de 129
Manual de AngularJS
Para hacer este ejercicio hemos seguido el prototipo realizado en el artculo anterior dedicado al ngRoute,
por lo que si no lo has ledo ya, es importante que lo hagas. En aquel ejemplo vimos cmo implementar
enlaces "profundos", en una barra de navegacin, que nos llevan a distintas vistas dentro de la misma
pgina.
Ahora vamos a mejorar el comportamiento de nuestra barra de navegacin. Aislaremos ese
comportamiento en un nuevo controlador independiente. Con ello tendremos dos controladores bien
separados:
Un controlador para la barra de navegacin de secciones
Un controlador para las vistas de mi aplicacin
Como puedes ver, son dos reas distintas de la aplicacin y por lo tanto tiene sentido usar controladores
distintos. El controlador de la navegacin sirve simplemente para implementar un comportamiento en mi
barra de navegacin, mientras que el controlador de las vistas independientes servira para mantener la
funcionalidad de esas vistas.
Echemos un vistazo en el cdigo HTML de este ejercicio
<body ng-app="app">
<nav ng-controller="navCtrl as nav">
<ul>
http://desarrolloweb.com/manuales/manual-angularjs.html
Pgina 89 de 129
Manual de AngularJS
De momento observars que en el HTML anterior solo parece que estemos usando un controlador, en la
etiqueta NAV. No nos hemos olvidado del otro, debes recordar que estaba declarado para cada una de las
vistas, que habamos definido con el $routeProvider.
$routeProvider
.when("/", {
controller: "appCtrl",
controllerAs: "vm",
templateUrl: "home.html"
})
// ..
Si te fijas, se trata de una clase llamada "marcado" que estar presente en la etiqueta LI en caso que el
mtodo estoy() que est dentro del scope "nav" nos devuelva un valor evaluado como verdadero.
<li ng-class="{marcado: nav.estoy('/opciones')}">
Este otro elemento de la lista tendr la clase "marcado" en caso que el mtodo estoy() de nav devuelva true
http://desarrolloweb.com/manuales/manual-angularjs.html
Pgina 90 de 129
Manual de AngularJS
Como puedes comprobar en el controlador se defini el mtodo estoy(), pero hay una cosa nueva que te
llamar la atencin seguramente. Se trata de la variable $location que est inyectada en la funcin que
implementa el controlador.
Conociendo $location
$location es un servicio ("service", tal como los llaman en AngularJS) que nos sirve para mantener y
trasladar informacin de la ruta actual del navegador. $location implementa una interfaz para el acceso a la
propiedad nativa de Javascript window.location, y nos sirve para acceder a elementos de la ruta actual,
conocer su estado y modificarlo. Por tanto, podemos saber en todo momento qu ruta tenemos y conocer
cuando el usuario ha navegado a otro lugar, ya sea con los botones de atrs o adelante o pulsando un enlace.
Pero no solo eso, existe un un enlace entre $location y window.location en las dos direcciones. Todo
cambio que realicemos en $location tambin tendr una respuesta en lo que se est mostrando en la barra
de direcciones del navegador. As como todo cambio de URL en el navegador tiene un efecto en el service
$location.
$location tiene una serie de mtodos bastante interesante a travs de los cuales podemos acceder a partes de
la URL que est en la barra de direcciones, desde el dominio, el puerto, protocolo, hasta la ruta en s de la
aplicacin.
En el ejemplo de antes estbamos usando $location.path() que nos devuelve el camino actual. Este mtodo
acepta dos juegos de parmetros.
Si llamamos a $location.path() sin parmetros, nos devuelve la ruta actual.
Si llamamos a $localtion.path() indicando un parmetro, entonces se cambia la ruta actual a aquello
que le hayamos indicado. La ruta debe comenzar por "/" el mtodo es lo suficientemente listo para
que, si no tiene la barra, se la pone automticamente.
As que, volviendo a nuestra funcin estoy(), apreciars que devolver true cuando la ruta enviada como
parmetro coincida con la ruta de nuestra aplicacin en ese instante, recuperada con $location.path().
map.estoy = function(ruta){
return $location.path() == ruta;
}
http://desarrolloweb.com/manuales/manual-angularjs.html
Pgina 91 de 129
Manual de AngularJS
Realmente este cdigo no es ms que una inicializacin de valores en un array llamado "vm.colores".
Ahora veamos el cdigo de las vistas independientes y veamos cmo usamos ese array de colores.
Observars que las vistas no hace nada muy espectacular, solo hemos colocado alguna cosa con fines
didcticos.
Vista "home.html": un simple recorrido a los colores del array para mostrarlos en cajas DIV.
<h1>Home</h1>
<div ng-repeat="color in vm.colores">{{ color }}</div>
Vista "opciones.html": un campo de texto donde escribir un color nuevo. Un botn donde enviamos el
contenido de ese campo de texto dentro del array de colores.
<h1>Opciones</h1>
Tienes {{ vm.colores }}
<p>
Agrega <input type="text" ng-model="vm.nuevocolor"> <input type="button" value="ok" ng-click="vm.colores.push(vm.nuevocolor)">
Pgina 92 de 129
Manual de AngularJS
aplicacin? Como vers ms tarde, s la hay, pero no lo haremos con los controladores.
Este comportamiento ocurre porque, cada vez que se accede a una vista independiente se est volviendo a
cargar el controlador, ejecutndose la funcin del controlador. Como en el controlador se inicializa el array
de colores, observars que cada vez que se usa en una vista ese array se inicializa de nuevo. En fin, cuando
pasas de una vista a otra el array de colores se vuelve a poblar con los colores que se haban configurado de
manera predeterminada en el controller.
La solucin a este problema pasa por usar factoras o servicios, pero es algo que veremos en el siguiente
artculo. Hasta ahora es importante que te quedes con esto: las funciones que implementan los
controladores son como constructores, que se llaman cada vez que el compilador del HTML de Angular
pasa por la vista.
http://desarrolloweb.com/manuales/manual-angularjs.html
Pgina 93 de 129
Manual de AngularJS
Terminamos el artculo pasado mencionando que las factoras nos podran solucionar la prdida de datos de
los controladores cuando cambiamos la vista. De modo que vamos a aprender a crearlas y utilizarlas.
Pero ese no es el nico caso donde encontrars utilidad en las factoras. Por ejemplo, algunas de las
necesidades que podramos tener y que los controladores no nos resuelven son:
1) Compartir datos entre varios controladores, lo que permite tener aplicaciones de verdad, capaces de
memorizar estados entre varias de sus pantallas.
2) Compartir datos entre varias vistas distintas. Por supuesto, sin usar las temidas variables globales. Eso es
justamente lo que vimos en el artculo anterior, que ya tengas uno o varios controladores, no comparten ni
se memorizan estados al pasar de una vista a otra.
http://desarrolloweb.com/manuales/manual-angularjs.html
Pgina 94 de 129
Manual de AngularJS
Pgina 95 de 129
Manual de AngularJS
Nota: Como observars, el mecanismo para crear la factora es el mismo que hacemos para crear los
controladores. Para crear el controlador usas el mtodo controller() y para la factora el mtodo
factory().
.factory("descargasFactory", function(){
var descargasRealizadas = ["Manual de Javascript", "Manual de jQuery", "Manual de AngularJS"];
var interfaz = {
nombre: "Manolo",
getDescargas: function(){
return descargasRealizadas;
},
nuevaDescarga: function(descarga){
descargasRealizadas.push(descarga);
}
}
return interfaz;
})
Esta factora se llama "descargasFactory". El nombre lo hemos definido en la llamada al mtodo factory.
Acurdate de este nombre, pues luego lo tendrs que usar al inyectar la dependencia de esta factora en tus
controladores.
Ese cdigo tiene una serie de detalles interesantes, desde el punto de vista de Angular y tambin desde el de
Javascript en general. Estudiar el cdigo anterior con detalle es suficiente para un nico artculo, porque
entran en juego diversos conceptos de la programacin orientada a objetos en Javascript. De todos modos,
te vamos a resumir un poco lo que encuentras.
Lo ms destacado sobre las factoras en AngularJS lo encuentras en la ltima lnea: "return interfaz;"
http://desarrolloweb.com/manuales/manual-angularjs.html
Pgina 96 de 129
Manual de AngularJS
Todas las factoras deben devolver algo. Lo que sea, aunque lo habitual como dijimos es devolver
un objeto. Por definicin debe de ser as en AngularJS.
Aquello que devuelves es lo que se conoce desde fuera de la factora. Por decirlo de otra manera, es
la interfaz pblica de uso de esa factora. Por eso hemos llamado a la variable que devolvemos en el
return "interfaz", porque es la serie de propiedades y mtodos que ests haciendo pblico para todo
el mundo que use esa factora. Lgicamente, esa "interfaz" no es ms que una manera nuestra de
llamar a la variable y t usars la que quieras.
Pero fjate que la variable "descargasRealizadas" es privada a la factora, pues no se devuelve en la
interfaz. Por tanto, ese array no podr ser accesible desde fuera de la factora. Podemos entenderlo
como una propiedad privada.
Para acceder al array "descargasRealizadas" se har uso de los mtodos definidos en "interfaz":
getDescargas() y nuevaDescarga(). Esos mtodos son pblicos, por haberlos definido en la interfaz
que devolvemos en la funcin de la factora y se podrn acceder desde cualquier lugar donde
tengamos disponible la factora.
Sin embargo no todos los datos que vamos a manejar en las factoras necesitamos hacerlos privados.
En concreto encontrars, la propiedad "nombre" que est dentro de nuestra interfaz y por lo tanto
es pblica y podr accederse tal cual desde fuera de la factora.
Nota: Para entender las ventajas hacer las cosas pblicas o privadas debers conocer algunos de los
conceptos bsicos de programacin en general y programacin orientada a objetos en particular, como
son la abstraccin y el encapsulamiento. Es una decisin de diseo de software, que debe tomar el
desarrollador y tanto Javascript como por extensin AngularJS tienen mecanismos para implementar
elementos pblicos o privados. As, como regla global en la programacin orienta a objetos, todo dato
debera ser definido como privado, a no ser que alguien de fuera te solicite que lo expongas
pblicamente.
vm.nombre = descargasFactory.nombre;
vm.descargas = descargasFactory.getDescargas();
http://desarrolloweb.com/manuales/manual-angularjs.html
Pgina 97 de 129
Manual de AngularJS
vm.funciones = {
guardarNombre: function(){
descargasFactory.nombre = vm.nombre;
},
agregarDescarga: function(){
descargasFactory.nuevaDescarga(vm.nombreNuevaDescarga);
vm.mensaje = "Descarga agregada";
},
borrarMensaje: function(){
vm.mensaje = "";
}
}
});
Dentro de nuestro controlador la variable descargasFactory que recibimos como parmetro contiene todos
los datos y funciones que hemos definido en la interfaz pblica de nuestra factora.
Por tanto:
descargasFactory.nombre contendr la propiedad "nombre" definida en la factory.
descargasFactory.nuevaDescarga() o descargasFactory.getDescargas() sern llamadas a los mtodos
que habamos definido en la factora.
Nota: Ojo, desde tu vista, en el HTML, no sers capaz de acceder a la factora. Es algo que ahora
pertenece al controlador y a travs del scope creado por ese controlador no puedes acceder a los datos
que tienen sus dependencias. Si quieres acceder a un dato de esa factora el mecanismo es volcar ese
dato en el scope. Eso lo hacemos al principio de ese controlador en las lneas:
vm.nombre = descargasFactory.nombre;
vm.descargas = descargasFactory.getDescargas();
Creo que con todo esto queda explicado el trabajo con las factoras en AngularJS. Ahora faltara un
poco de tiempo por tu parte para poder ponerlo en prctica.
Este artculo es obra de Alberto Basalo
Fue publicado por primera vez en 15/12/2014
Disponible online en http://desarrolloweb.com/articulos/factorias-factory-angularjs.html
Pgina 98 de 129
Manual de AngularJS
En Angular no existe un nico mbito, puedes tener (tendrs) diferentes scopes en diferentes partes de tu
cdigo, anidados o en paralelo. Los scope se crean automticamente para cada uno de tus controladores y
adems existe un scope raz para toda tu aplicacin. A continuacin te ensearemos a trabajar con ellos,
almacenando datos y recuperndolos.
Ese "algo" es un dato que tienes almacenado en el scope desde el controlador. Como sabes, con esa
expresin lo vuelcas en la pgina. Tambin podrs acceder al scope cuando usas la directiva ng-model y
defines un dato en tu modelo.
<input type="text" ng-model="miDato">
Como se deca, el scope nos sirve para trasladar esos datos entre el controlador y la vista. Nosotros para
poder acceder a "algo" o a "miDato" no necesitamos enviarlo desde el controlador a la vista ni de la vista al
http://desarrolloweb.com/manuales/manual-angularjs.html
Pgina 99 de 129
Manual de AngularJS
controlador, salvo crear esa propiedad en el $scope. Lo bonito, que vimos en el artculo de Binding en
Angular, es que cuando el dato se modifica, ya sea porque se le asigna un nuevo valor desde el controlador o
porque se cambia lo que hay escrito en el INPUT de la vista, la otra parte es consciente de ese cambio sin
tener que suscribirnos a eventos.
Lo que queremos que se vea ahora es que el scope creado por ese controlador "miAppController" tiene
validez dentro de ese cdigo HTML en el lugar donde se ha definido la directiva ngController. Es decir, los
elementos que asignes a $scope dentro de tu controlador se podrn ver desde la etiqueta DIV y todas sus
hijas, pero no desde etiquetas que se encuentren fuera, como es el caso del SECTION que hay despus.
En este caso podrs generar datos en el scope de dos maneras, o bien a travs del mismo objeto $scope que
puedes inyectar, tal como acabamos de explicar, o bien a travs de la variable this dentro de la funcin.
.controller('pruebaAppCtrl', function($rootScope){
var modeloDeLaVista = this;
modeloDeLaVista.otroDato = "Esto est ahora en el scope, para acceder a travs de un alias";
});
Gracias al alias en la vista podrs acceder a ese dato con una expresin como esta:
{{ vm.otroDato }}
http://desarrolloweb.com/manuales/manual-angularjs.html
Manual de AngularJS
Este alias del scope nos simplificar la vida cuando estemos trabajando con varios mbitos. Enseguida lo
veremos.
Cuando guardas algo en el mbito raz puedes acceder a ese valor, desde tu vista, a travs del nombre de la
propiedad que has creado en $rootScope.
<div ng-controller="pruebaAppCtrl">
{{ scopeNormal }}
<br />
{{ scopeRaiz }}
</div>
Como ves, en este ejemplo accedemos de la misma manera a un dato que tienes en el scope de este
controlador y a un dato que tiene en el scope raz. Esto es as porque en AngularJS, si una variable del
modelo no se encuentra en el scope actual, el propio sistema busca el dato en el scope padre. Si no, en el
padre y as sucesivamente.
Conociendo $parent
El problema es cuando tienes un dato con el mismo nombre en dos scopes distintos.
.controller('pruebaAppCtrl', function($scope, $rootScope){
//sobrescribo una variable del scope
//en realidad son dos datos distintos con dos valores distintos
//uno lo tengo en el scope del controlador y otro en el scope raz "root"
$scope.repetido = "Algo en el scope normal";
$rootScope.repetido = "Algo en el scope raz";
});
En ese caso, si en a vista hacemos algo como {{ repetido }} vers que existe una ambigedad, pues ese
valor puede significar dos cosas, dependiento si miramos en un scope u otro. Angular resuelve esa situacin
devolviendo el dato del scope ms especfico. Osea, te dar el valor que tiene en $scope.repetido y no
podrs acceder a $rootScope.repetido, a no ser que uses $parent.
http://desarrolloweb.com/manuales/manual-angularjs.html
Manual de AngularJS
$parent permite acceder al scope "padre", eso en caso que tengas dos controladores uno dentro de otro. O
en el caso que solo tengas un controlador con $parent podrs acceder al scope raz.
As pues, para acceder a ambos valores podra usar un HTML como este:
<div ng-controller="pruebaAppCtrl">
{{ repetido }} --- {{ $parent.repetido }}
</div>
El primer "repetido" nos permite acceder al dato que tenemos en el scope actual y por su parte
$parent.repetido nos permite acceder al dato que habamos guardado sobre $rootScope.
Javascript:
.controller('pruebaAppCtrl', function($scope, $rootScope){
$scope.scopeNormal = "Esto lo coloco en el scope normal de este controlador...";
$rootScope.scopeRaiz = "Esto est en el scope raz";
Puedes apreciar ms o menos todo lo que venimos comentando sobre los mbitos, pero lo vers mejor de
una manera visual con la extensin Angular Batarang.
Angular Batarang
Existe una herramienta que se integra en Google Chrome que te sirve de inspector de scopes en AngularJS.
Se llama "Batarang" y nos permite ver de una manera rpida lo que tenemos en los diferentes scopes de
nuestra aplicacin.
Para desarrollar con AngularJS es imprescindible. Seguro que la conoces.
http://desarrolloweb.com/manuales/manual-angularjs.html
Manual de AngularJS
Como ves, las herramientas para desarrolladores de Chrome tienen ahora una nueva pestaa que me
permite examinar los distintos scopes de esta aplicacin. En la imagen anterior puedes ver dos pantallas,
examinando el scope raz y el scope comn generado por un controlador.
Finalizamos por aqu, a la espera de publicar un artculo que nos permita construir controladores anidados,
o en paralelo, donde podremos observar tambin diferentes construcciones de mbitos.
Manual de AngularJS
scopes tambin se colocarn lado a lado o bien unos dentro de otros. Lo veremos mejor con ejemplos de
cdigo.
Controladores en paralelo
En este caso tenemos un controlador al lado del otro, en el cdigo HTML. No es la primera vez en este
Manual de AngularJS que implementamos controladores en paralelo, as que no debera de representar
mucho problema.
Para hacer dos controladores funcionando en paralelo podremos tener un HTML en el que se define un
controlador al lado del otro.
<body ng-app="app">
<header ng-controller="headerCtrl">
{{ scopeHeader }}
</header>
<section ng-controller="sectionCtrl">
{{ scopeSection }}
</section>
</body>
El Javascript con el que se declaran y definen estos controladores lo puedes ver a continuacin:
var app = angular.module("app", [])
Como sabes, en cada controlador se crea un scope son independiente. Todos dependen de un scope raz
que sigue existiendo y dentro de ste tendremos los dos scopes de cada controlador. Si inspeccionamos
estos mbitos con la extensin Batarang obtendremos esto:
http://desarrolloweb.com/manuales/manual-angularjs.html
Manual de AngularJS
Desde un scope no puedo acceder al otro. Eso quiere decir que los elementos definidos para el HEADER,
como la propiedad "$scope.scopeHeader", no se puede acceder desde el controlador definido en el
SECTION.
Nota:En general, si quisiramos compartir datos entre ambos controladores nos tocara implementar
una factora o servicio, o quizs si lo consideramos ms adecuado para nuestro caso, crear datos en el
scope raz, inyectando $rootScope en los controladores y asignando propiedades en ese objeto. El
$rootScope lo conocimos en el artculo titulado Scope en Angular, manejando mbitos con $parent.
Controladores anidados
Las caractersticas y las posibilidades de navegacin entre distintos scopes las vemos mejor todava en el
caso de los controladores anidados. En este caso tenemos un HTML en el que se coloca un controller y
dentro de ste otro pedazo de HTML donde se declara otro elemento con un nuevo controller.
<body ng-app="app">
<section ng-controller="sectionCtrl">
<p>
{{ scopeSection }}
</p>
<article ng-controller="articleCtrl">
{{ scopeArticle }}
</article>
</section>
</body>
Ahora, en la declaracin de los controllers en Javascript, observars que no hay ningn indicio que en el
HTML estn anidados. De hecho es lo correcto, pues los controladores deben ser agnsticos a cmo est
hecho nuestro HTML.
var app = angular.module("app", [])
http://desarrolloweb.com/manuales/manual-angularjs.html
Manual de AngularJS
En este caso podremos observar que los mbitos estn uno dentro de otro, gracias a la extensin Batarang.
Lo interesante en este caso es que podemos acceder desde un scope a los datos declarados en un scope
padre, gracias a la anidacin definida en el HTML.
<section ng-controller="sectionCtrl">
<p>
{{ scopeSection }}
</p>
<article ng-controller="articleCtrl">
{{ scopeArticle }}
<p>
Si quiero, puedo acceder al scope del elemento padre <b>{{ scopeSection }}</b>
</p>
</article>
</section>
Como puedes ver, dentro del ARTICLE, definido con controller "articleCtrl" podemos acceder
perfectamente a un dato que est en el scope del controlador padre: {{scopeSection}}.
Nota:Esto, que ya se explic, es gracias a que en Angular, si no se encuentran los datos en el scope
actual, automticamente se busca en el scope padre, subiendo todos los niveles que haga falta hasta
llegar al scope raz. Ese es un comportamiento automtico para el cual no necesitamos configurar ni
programar nada.
http://desarrolloweb.com/manuales/manual-angularjs.html
Manual de AngularJS
La variable $parent contiene simplemente una referencia al scope padre. ste puede ser el scope raz o si
tenemos controladores anidados es el del nivel superior en la anidacin. El cdigo HTML anterior
podramos haberlo escrito as.
<section ng-controller="sectionCtrl">
<p>
{{ scopeSection }}
</p>
<article ng-controller="articleCtrl">
{{ scopeArticle }}
<p>
Si quiero, puedo acceder al scope del elemento padre <b>{{ $parent.scopeSection }}</b>
</p>
</article>
</section>
Prcticamente no hay ninguna diferencia, excepto que cuando accedemos desde el ARTICLE a un modelo
(dato) del SECTION lo hacemos a travs de $parent:
{{ $parent.scopeSection }}
En este caso usando $parent el cdigo puede quedar un poco ms claro pues el que lo lea sabr que ese
modelo est en el scope del controlador padre. Sin embargo, enseguida veremos otra manera de hacer esto
en la que el cdigo puede quedar ms claro todava.
Como puedes observar, tanto el "manualCtrl" como "articuloCtrl" tienen un modelo llamado "nombre" que
ser el ttulo del manual o el ttulo del artculo. Si desde el controller del artculo queremos acceder al
nombre del manual, no podemos escribir {{ nombre }} porque nos saldra el ttulo del artculo. En ese caso
tenemos que escribir la ruta $parent.nombre.
http://desarrolloweb.com/manuales/manual-angularjs.html
Manual de AngularJS
Esta situacin y uso de $parent se puede extender a mltiples niveles de anidacin. Por ejemplo podramos
tener comentarios dentro de los artculos y en ellos el modelo "nombre" que en este caso sera el autor del
comentario. Desde el scope de los comentarios podramos acceder a los dos scope padre, tanto artculo
como el manual, encadenando $parent.
<section ng-controller="manualCtrl">
<p>
Manual: {{ nombre }}
</p>
<article ng-controller="articuloCtrl">
Artculo: {{ nombre }}
<p>
Este artculo pertenece al manual {{ $parent.nombre }}
</p>
<p ng-controller="comentariosCtrl">
Este comentario lo escribe {{ nombre }}
<br>
Pertenece al artculo {{ $parent.nombre }}
<br>
Que a su vez pertenece al manual {{ $parent.$parent.nombre }}
</p>
</article>
</section>
Nota:La sintaxis del "controller as" la hemos usado en diversas ocasiones a lo largo de este manual. La
explicamos por primera vez en el artculo sobre los cdigos para hacer un controlador y sus variantes.
http://desarrolloweb.com/manuales/manual-angularjs.html
Manual de AngularJS
Supongo que se aprecian las diferencias. Ahora cada uno de los scopes que tenemos en cada controlador
tiene un alias y dentro de ese controller y todos los hijos existe ese alias. A travs del alias somos capaces de
acceder al modelo declarado en cada controlador, no solo en el que estamos, sino tambin en todos los
controladores padre.
Este modo de usar los controladores produce un cambio de operativa en nuestro Javascript que ya se
explic tambin. Dejamos el cdigo fuente para que encuentres las diferencias.
var app = angular.module("app", [])
Puedes ver el aspecto que tendra este ejemplo con el inspector de los scopes de Batarang:
http://desarrolloweb.com/manuales/manual-angularjs.html
Manual de AngularJS
Con esto termina nuestro recorrido a los scopes de AngularJS, esperamos que esta informacin te haya
resultado de utilidad y comprendas mejor el alcance de los mbitos en los controladores y el modo de
trabajar con ellos.
Angular Material
Este mdulo para AngularJS nos permite implementar de una manera muy cmoda un diseo de
aplicacin con las directrices de Material Design de Google.
En este artculo vamos a hacer una review de un proyecto que sin duda resultar muy atractivo para todos
los desarrolladores de AngularJS. Se trata de Angular Material, un mdulo para AngularJS que nos permite
implementar diseos basados en Material Design.
Bsicamente lo que nos ofrece no es solo una hoja de estilos, capaz de aplicar la apariencia definida en
Material Design, sino toda una serie de componentes que enriquecern mucho el catlogo de interfaces de
usuario disponibles al implementar una web.
Para quien ya viene trabajando desde hace tiempo con AngularJS, podemos hacer un paralelismo con otra
librera interesante, llamada AngularUI, que nos ofrece una cantidad enorme de componentes como
selectores de fecha, regillas, deslizadores, etc. En este caso Angular Material sera un competidor. Podramos
usarlos juntos, pero cada uno tiene una base de CSS y un look & feel diferente, por lo que quizs no sea tan
buena idea.
http://desarrolloweb.com/manuales/manual-angularjs.html
Manual de AngularJS
Angular Material est realizado por Google y puedes acceder al sitio web en la URL:
https://material.angularjs.org
Te recomendamos echar un vistazo a los demos, donde encontrars selectores de fecha, cajas de dilogo,
regillas, tarjetas, botones, iconos, barras de tareas, etc.
Angular Material es una excelente opcin para programadores, que no tienen habitualmente habilidades de
diseo. Usando las directivas que nos ofrece podremos producir aplicaciones que son estticamente
brillantes, junto con una serie de componentes adicionales al propio HTML con un look & feel muy
trabajado.Los podremos producir prcticamente sin necesidad de escribir nada de CSS, consiguiendo
diseos muy atractivos, aprovechando, pero sin necesidad de dominar, caractersticas modernas de CSS
como por ejemplo Flexbox.
El nico "pero" podramos decir que es que las aplicaciones se pueden parecer unas a las otras. Para una
"home page" de una empresa quizs no es la mejor opcin, porque generalmente se desear una esttica
diferenciada, pero en el caso de aplicaciones de gestin y aplicaciones web en general es algo interesante,
porque nos asegura que los usuarios se sentirn familiarizados con la aplicacin. Adems, las opciones de
personalizacin tambin dependern de nosotros y de cmo queramos modificar el diseo y crear nuestras
propias interfaces y componentes, puesto que usar Material Design no implica que estemos restringidos a
las directivas que nos dan ya listas.
Qu es Material Design
Material Design es un conjunto de especificaciones sobre un estilo de diseo muy popular. Si tienes un
telfono Android, o accedes a servicios de Google como G+, Inbox, etc. ya sabrs lo que es, aunque quizs
no le has dado todava nombre.
Bsicamente lo que nos dicen es cmo podemos disear interfaces de usuario, cules son las cosas que se
deben y no se deben hacer, qu tipos de componentes de interfaces se pueden usar, etc. Como en este
artculo no discutimos Material Design os dejamos simplemente un enlace para que consultis las propias
guas de Google de Material Design.
Manual de AngularJS
Bower:
bower install angular-material
npm:
npm install angular-material
jspm:
jspm install angular-material
A continuacin debemos incluir el cdigo de Angular Material en nuestro proyecto, para lo que realizars
los pasos:
1. Instalacin del CSS
<link rel="stylesheet" href="/ruta_a/angular-material/angular-material.css">
Nota: Ojo, que la ruta al archivo depender de qu gestor de dependencias ests usando en tu proyecto.
Nota: De nuevo, las rutas dependern de si lo has instalado con Bower, npm o jspm.
Manual de AngularJS
ten en cuenta el requisito de contar con la librera AngularJS al menos en su versin 1.4.8. Se
recomienda en el momento de escribir este artculo AngularJS 1.5.
Hay componentes adems que tambin nos soportan comportamientos, como es el caso de las cajas de
dilogo. En este caso habr tambin que documentarse para ver cmo se pueden producir no solo con las
etiquetas necesarias para incluirlas en el HTML de la pgina, sino tambin con el Javascript necesario para
ponerlas en funcionamiento o los eventos que produzcan cuando el usuario interaccione con los
componentes.
En si el proyecto es muy amplio, pero merece la pena el esfuerzo de estudiarlo. Entender y dominar sus
componentes llevar su tiempo, pero a la larga nos ahorrar mucho trabajo del lado del diseo y nos asegura
un nivel de calidad esttico y una usabilidad elevada en nuestras aplicaciones.
Acabamos esta review agradeciendo a Alberto Basalo sus clases en el Curso de Front Edge de EscuelaIT,
donde hemos podido realizar una aplicacin AngularJS con Angular Material, lo que sin duda facilita
enormemente comenzar a usar esta librera y suavizar enormemente la curva de aprendizaje.
Manual de AngularJS
Fue publicado por primera vez en 16/02/2016
Disponible online en http://desarrolloweb.com/articulos/angular-material.html
http://desarrolloweb.com/manuales/manual-angularjs.html
Manual de AngularJS
Directivas Vs componentes
Las directivas de AngularJS, as como los componentes se crean aadiendo la funcionalidad a un mdulo
(module) igual que otros elementos como controladores o factoras.
http://desarrolloweb.com/manuales/manual-angularjs.html
Manual de AngularJS
La diferencia fundamental es que, mientras que las directivas reciban una funcin, igual que controllers o
factorys, los componentes reciben un objeto. Realmente es parecido en el sentido en el que las directivas al
final deban devolver un objeto y los componentes directamente sirven ese objeto al mtodo component().
Directivas se declaraban as:
.directive('nombre_directiva', function() {
return {
//...
};
});
Este es uno de los muchos detalles, puesto que muchos otros conceptos han sido simplificados con
respecto a las directivas.
Pero en la prctica los componentes adems nos permiten extender el HTML de otra manera, creando
nuevas etiquetas completas que podremos incorporar y que esconden dentro sus propias complejidades,
permitiendo una mayor reutilizacin y manteniendo encapsulada su complejidad.
Esto nos permite simplificar el marcado de las vistas. Si antes tenamos algo como:
<h2>Contactos</h2>
<ul class="lista">
<li ng-repeat="elem in vm.contactos">
{{elem.nombre}} <span>{{elem.telefono}}</span>
</li>
</ul>
El componente contactos encapsula todo ese marcado y a su vez podra estar usando otros componentes
para encapsular cada uno de los contactos individuales, ya que unos componentes se apoyan en otros para
resolver los problemas.
Si tenemos varias listas de contactos simplemente le pasamos un juego de datos distinto y listo. Si tenemos
otro proyecto que maneje contactos, se hace mucho ms cmodo reutilizar el componente. Tambin
permite aislar mejor los distintos componentes del proyecto entero, el scope y realizar testing de cada
http://desarrolloweb.com/manuales/manual-angularjs.html
Manual de AngularJS
componente de manera independiente, entre otras ventajas con respecto a las directivas.
Como ves es como si hubisemos creado una nueva etiqueta, que el navegador entender perfectamente
gracias a AngularJS. No obstante, por la construccin de nuestro ejemplo, donde estamos usando la
inicializacin bsica de Angular, vamos a necesitar el ng-app en la etiqueta BODY o HTML. Mira el cdigo
html completo de nuestro ejemplo.
<!DOCTYPE html>
http://desarrolloweb.com/manuales/manual-angularjs.html
Manual de AngularJS
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Probando componentes</title>
</head>
<body ng-app="appProbandoComponent">
<probando-component></probando-component>
<script src="bower_components/angular/angular.min.js"></script>
<script>
angular
.module("appProbandoComponent", [])
.component("probandoComponent", {
template: [
'<div class="miclase">',
'<span>Esto es algo de HTML en el componente</span> ',
'<b>Angular Rules!</b>',
'</div>'
].join('')
});
</script>
</body>
</html>
http://desarrolloweb.com/manuales/manual-angularjs.html
Manual de AngularJS
El Javascript del componente: Ahora veamos nuestro Javascript para definir el componente. Lo ms
importante aqu es que hemos usado un mdulo independiente para este componente. Sobre este "module"
crearemos el componente en s con el mtodo component(). Lo interesante de esta alternativa es que para
reutilizar el componente en otro proyecto ser simplemente traernos este mdulo y declararlo como
dependencia.
Este sera nuestro archivo mi-header.js
angular.module("miHeader", [])
.component("miHeader", {
templateUrl: "./components/mi-header/mi-header.html"
});
En esta ocasin comprobars que en lugar del marcado del componente, definido con el atributo "template"
que vimos antes, tenemos el atributo "templateUrl" donde indicamos la ruta del HTML del componente,
desde la raz de nuestro proyecto.
Marcado del componente: El cdigo HTML del componente ahora lo tenemos en un archivo .html, lo
que nos ofrece muchas ventajas de cara al mantenimiento, como te imaginars.
Este sera el cdigo HTML de nuestro archivo mi-header.html
<header>
<h1>Esta es mi cabecera</h1>
<div>Controles de cabecera</div>
</header>
http://desarrolloweb.com/manuales/manual-angularjs.html
Manual de AngularJS
Usamos el componente desde el index.html del proyecto: Ahora nos queda usar el componente. Esto
lo hacemos en el index.html, colocando la etiqueta del componente. Pero adems recuerda definir el ng-app
con el nombre del mdulo principal de la aplicacin, as como incluir los diferentes scripts.
Veamos el cdigo completo de index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Probando componentes</title>
</head>
<body ng-app="appProbandoComponent">
<mi-header></mi-header>
<script src="bower_components/angular/angular.min.js"></script>
<script src="components/mi-header/mi-header.js"></script>
<script src="app.js"></script>
</body>
</html>
Todo este cdigo tambin depender del gestor de dependencias que uses y el tipo de arranque que
prefieras en tu aplicacin Angular. Pero repara que para usar el componente simplemente colocamos la
etiqueta HTML "mi-header".
<mi-header></mi-header>
De momento eso es todo. Seguramente podrs darte cuenta de las ventajas de la componetizacin en
AngularJS. Ahora es empezar a usarla. No obstante, seguiremos informando sobre cmo realizar otras cosas
con componentes, porque hasta ahora con lo que has visto solo son como "includes" de cdigo HTML, y
realmente podemos derivar mucha lgica de nuestra aplicacin dentro de los componentes.
Manual de AngularJS
Disponible online en http://desarrolloweb.com/articulos/componentes-angularjs-15.html
http://desarrolloweb.com/manuales/manual-angularjs.html
Manual de AngularJS
.component('cuentaClics', {
templateUrl: './components/cuenta-clics/cuenta-clics.html',
controller: function(){
var vm
= this;
vm.numClics = 0;
vm.incrementaClic = function(){
vm.numClics ++;
}
}
});
Tambin como alternativa es posible indicar el nombre de un controlador que haya definido en ste u otro
mdulo. Por tanto el cdigo que ves a continuacin tendr el exactamente el mismo efecto:
angular.module('cuentaClics', [])
.controller('CuentaClicsController', function(){
var vm
= this;
vm.numClics = 0;
vm.incrementaClic = function(){
vm.numClics ++;
}
})
.component('cuentaClics', {
templateUrl: './components/cuenta-clics/cuenta-clics.html',
controller: 'CuentaClicsController'
});
Como has comprobado en este sencillo controlador tenemos las dos cosas que se suelen encontrar en ellos,
datos como es el caso de "numClics" y funciones para realizar comportamientos, como es el caso de
"incrementaClic".
Nota: Nota: Con el mtodo de trabajo que se conoce con "Controller As" ramos capaces de definir
diversos nombres para conocer a los controladores dentro de diversos scopes que puede tener una
aplicacin, de modo que se puedan anidar controladores y no tener problemas para acceder a datos o
mtodos de controladores especficos, incluso cuando existen propiedades y valores que tienen los
mismos nombres. En controllers de components tambin podemos asignar nombres para definir cmo
se debe de conocer al controlador dentro del HTML del componente, usando la propiedad
"controllerAs":
http://desarrolloweb.com/manuales/manual-angularjs.html
Manual de AngularJS
.component('cuentaClics', {
templateUrl: './components/cuenta-clics/cuenta-clics.html',
controller: 'CuentaClicsController',
controllerAs: 'vm'
});
Sin embargo en principio no necesitaramos cambiar nunca ese nombre de controlador, ya que la
arquitectura de componentes hace que los datos ofrecidos por un controlador estn encapsulados
dentro de ese componente. Es decir, en componentes hijo no somos capaces de acceder a los datos de
los controladores de los padres u otros antecesores y por ello no es necesario el cambio del nombre del
controlador con "controllerAs".
Solo para aclarar posibles dudas cabe adelantar que el mecanismo para compartir datos de unos
componentes a otros es el bindeo, enviando datos a los componentes hijos que los puedan necesitar.
Esas tcnicas de binding en componentes son las que vamos a tratar en el artculo siguiente.
En este HTML podrs encontrar el uso de la propiedad y mtodo que habamos definido en el controlador
de nuestro componente cuentaClics.
<div>
<h2>Cuenta Clics</h2>
<p>Hasta el momento has hecho {{$ctrl.numClics}}</p>
<button ng-click="$ctrl.incrementaClic()">Haz clic para incrementar el contador</button>
</div>
Usar un componente
En este momento asumimos que la mayora conocer el flujo para usar un componente como este, que
hemos definido en un mdulo independiente. Si es tu caso puedes saltarte esta seccin, pero si ests
comenzando con Angular o componentes quizs te vengan bien las siguientes pautas.
Nota: Nuestro componente es bueno colocarlo en un mdulo independiente, donde solo est este
componente, para que podamos reutilizarlo fcilmente entre distintos proyectos, o incluso para que lo
podamos compartir con otras personas.
1.- Definimos el componente, normalmente en una carpeta independiente donde estarn todos los ficheros.
De momento tendremos el .js de la declaracin del componente, en su mdulo independiente, y el .html del
template.
2.- Incluimos el script donde est el componente (el .js de la declaracin). Esto lo podrs realizar de diversas
formas, donde la ms sencilla sera colocar la correspondiente etiqueta SCRIPT con el src hacia la ruta del
componente.
<script src="components/cuenta-clics/cuenta-clics.js"></script>
http://desarrolloweb.com/manuales/manual-angularjs.html
Manual de AngularJS
3.- Al crear el mdulo general de nuestra aplicacin, definimos la dependencia con el mdulo donde hemos
creado nuestro component.
angular.module('miapp', [ 'cuentaClics'])
4.- Luego ya solo queda usar el componente, las veces que sean necesarias, usando la etiqueta
correspondiente con el nombre del componente que hayamos creado. Solo ten en cuenta que si el nombre
del componente en Javascript tiene notacin "camel case", en el HTML tenemos que separar las palabras
por guiones.
<cuenta-clics></cuenta-clics>
Eso es todo, tu componente debera funcionar sin problemas. Si no es as, revisa que la ruta en el src del
script est correcta, que el nombre del mdulo donde est el component est correcto, tenga notacin camel
case para separar palabras y que est definida la dependencia en el mdulo de tu aplicacin. Revisa por
ltimo que la etiqueta HTML tiene separadas las palabras por guiones.
En la siguiente entrega de esta serie dedicada a componentes en Angular veremos algo muy interesante
como es el binding entre componentes para facilitar la interoperabilidad.
http://desarrolloweb.com/manuales/manual-angularjs.html
Manual de AngularJS
Arquitectura de componentes
Cada componente es responsable por hacer una parte del trabajo de la aplicacin, pero para trabajar no
estn solos, sino que deben relacionarse y comunicarse unos con otros.
Bajo la arquitectura de componentes tenemos un rbol de elementos. Forman una estructura donde unos
componentes incluyen a otros, donde cada uno de ellos encapsula un HTML y cierta lgica de aplicacin.
La clave es que cada componente tiene su scope (mbito) independiente y nico. Un componente solo
conoce aquellos datos que su controlador maneja, no pudiendo acceder a los scope de otros componentes,
ya sean padres o hijos. Esa estructura facilita el desarrollo de aplicaciones, porque uno puede saber a priori
dnde est el cdigo que afecta a cada parte de la aplicacin.
Esto se ve mejor en contraposicin con una aplicacin tradicional de Angular:
En una aplicacin de Angular, desde cualquier componente del cdigo podemos afectar a cualquier
parte de la aplicacin, ya que el mbito se puede compartir por mecanismos como la herencia de
scopes y los observadores. Es una situacin prctica que a veces deriva en problemas al entender las
aplicaciones y al depurarlas.
En una aplicacin de componentes cada componente afecta al HTML que tiene dentro y puede
modificar los datos que se estn mostrando dentro de ese HTML. Eso hace fcil localizar el cdigo
que afecta a los datos de cualquier parte de la aplicacin.
Para que componentes independientes puedan colaborar entre s, de modo que consigamos entre todos una
aplicacin, es necesario que se intercambien datos. Esto se hace por medio de mecanismos de binding y se
pueden producir a varios niveles.
En el anterior HTML tenemos una propiedad llamada "dato" que dentro del componente equivale a
http://desarrolloweb.com/manuales/manual-angularjs.html
Manual de AngularJS
"valor".
En el Javascript del componente, en su definicin, se debe declarar qu propiedades se pueden recibir y qu
tipos de binding se van a implementar sobre ellas. Para ello se debe declarar cada una de las propiedades en
el objeto "bindings", indicando un smbolo que aclare qu tipo de bindeo se va a realizar.
angular.module("componenteBinding", [])
.component("componenteBinding", {
templateUrl: "./js/components/componente-binding/componente-binding.html",
controller: "componenteBindingController"
},
bindings: {
user: "=",
num: "@"
}
});
En el cdigo anterior se est declarando un binding con dos atributos, "user" y "num".
Tipos de bindeo
El bindeo entre componentes puede ser de varios tipos. Podemos tener binding a dos direcciones, algo
tpico de Angular, donde los datos viajan desde un componente al otro y desde el segundo al primero. Pero
ahora en Angular 1.5 tambin podemos crear binding en una sola direccin, as como tambin se puede
realizar envo de datos en crudo, que una vez se entregan no quedan bindeados ni en una direccin ni en
otra.
En la declaracin bingings, cada tipo de bindeo se define por medio de un smbolo, los principales son:
"=": esto sirve para entregar una referencia a un objeto. Por tanto cualquier cosa que se est entregando se
comparte entre componentes.
"@": esto sirve para entregar un valor. No existe binding de ningn tipo.
(Smbolo "menor qu"): esto sirve para bindear en una nica direccin, o 1 way binding. El padre le
transfiere al hijo un valor, pero aunque lo modifique el hijo el nuevo valor no viaja al padre. Sin embargo, si
el padre lo cambia, s se cambia en el hijo.
Manual de AngularJS
Antes de terminar vamos a ver un ejemplo para ilustrar todo lo que hemos aprendido sobre componentes a
lo largo de los anteriores artculos. Es un ejemplo sencillo pero prctico. Son dos componentes que se
transfieren informacin para completar un objetivo comn, que es crear un listado de usuarios.
Tendremos un componente padre que es el listado completo de usuarios y un componente hijo que es cada
uno de los item del listado (el detalle de un usuario nico). Por decirlo de otro modo, el componente padre
producir una repeticin y cada uno de los item de esa repeticin ser implementado por un componente
hijo.
Hemos llamado a nuestros componentes "user-list" y "user-detail". Cada componente a su vez tiene dos
archivos de cdigo, uno el .js, con el registro del componente en s, y otro .html con el HTML local de ese
componente.
Comenzamos viendo el cdigo de mi listado de usuarios: user-list
El archivo user-list.js
angular.module("userList", [])
.component("userList", {
templateUrl: "./js/components/user-list/user-list.html",
controller: function($http){
var vm = this;
$http.get("http://jsonplaceholder.typicode.com/users")
.then(function(respuesta){
vm.usuarios = respuesta.data;
})
}
});
Como puedes ver, me traigo el listado de usuarios de un servicio REST. Ese listado de usuarios lo vuelco en
la variable vm.usuarios, que es el nico dato que este controlador ofrece a la vista.
Cdigo de user-list.html
<user-detail ng-repeat="item in $ctrl.usuarios" usuario="item" numero="{{$index}}"></user-detail>
El cdigo HTML es un nico componente que tiene un ng-repeat, por lo que se produce la iteracin por
todos los usuarios. Cada usuario se muestra con el componente user-detail. A ese componente le estamos
pasando dos bindings, cuyos valores se entregan por atributos del HTML.
Es importante reparar la diferencia entre el atributo usuario="item" y numero="{{$index}}". La diferencia
de las dos llaves es que {{$index}} lo vamos a pasar por valor, no por referencia. Lo confirmars en el
siguiente listado.
Cdigo de user-detail.js
http://desarrolloweb.com/manuales/manual-angularjs.html
Manual de AngularJS
angular.module("userDetail", [])
.component("userDetail", {
templateUrl: "./js/components/user-detail/user-detail.html",
controller: function(){
var vm = this;
vm.cambiarEmail = function(){
vm.usuario.email = "[email protected]";
}
},
bindings: {
usuario: "=",
numero: "@"
}
})
Aqu la novedad est en "bindings", donde estamos declarando los dos bindeos que este componente espera
recibir. Ahora lo importante es:
El campo "usuario" lo recibe como bindeo. Es un objeto, pasado por referencia. En ese caso se
produce un 2 way binding.
El campo "numero" lo recibe como valor. Le llega solo un dato que, por mucho que se cambie en el
componente, no se transfiere nada al padre.
Adems fjate que el controlador casi no tiene cdigo. Solo hemos definido una funcin para cambiar un
dato el objeto usuario, de modo que se compruebe si se produce el binding hacia arriba.
En la vista podremos usar los bindeos como si fueran datos proporcionados por el propio controlador y en
el controlador tambin los podremos usar como si fueran propiedades suyas normales. Esto lo compruebas
con el siguiente listado.
Archivo user-detail.html
<div class="user" ng-click="$ctrl.cambiarEmail()">
<h2>{{$ctrl.numero}})</h2>
Nombre: {{$ctrl.usuario.name}}
<br>
Email: {{$ctrl.usuario.email}}
</div>
Aprecia como los datos que me vienen por el binding los trato como si fueran del controlador: $ctrl.numero
y $ctrl.usuario
Puedes encontrar el cdigo de estos ejemplos de componentes en Angular 1.5 en Github.
http://desarrolloweb.com/manuales/manual-angularjs.html
Manual de AngularJS
http://desarrolloweb.com/manuales/manual-angularjs.html