TUT:Construyendo un SPA usando AngularJS con ASP.NET Web API - Parte 2


Esta es la  segunda parte de la serie  Construyendo una SPA(Single Page App)  usando AngularJS. Las partes  desarrolladas son tres:


En el post anterior hemos hecho todos los trabajos necesarios para arrancar con nuestra aplicación con AngularJS, ahora nos enfocaremos en implementar los casos de uso que mencionamos en el post introductorio, aquí veremos como que tan potente y divertido trabajar con AngularJS puede ser. Empezaremos construyendo esos requerimiento de de abajo hacia arriba, así que vamos a empezar por servicios y nos moveremos hasta las vistas.


Paso 1: Agregando servicio para la comunicación  con el API FourSquare
Como lo discutimos anteriormente, los servicios en AngularJS son objetos singleton responsables de hacer ciertas tareas, o pueden ser usados para compartir lógica de negocios. Para usar estos servicios personalizados creados, necesitamos especificar el nombre del servicio en el controlador, filtro , directiva, etc. y AngularJS inyectará estos objetos singleton. AngularJS es construido en una manera que será capaz de administrar estos servicios personalizados creados, así que podemos usarlos en cualquier lugar de nuestra aplicación.
Hay diferentes maneras de crear Servicios AngularJS, dos de ellos son los métodos Service o Factory, ambos nos proveen con objetos singleton compartidos, y la sola diferencia es cómo son creados, no voy a profundizar más las diferencias y usaremos Factory para crear los servicios.
Así que vamos a agregar un nuevo archivo JS llamado “explorarLugarService.js” dentro la carpeta “app->services”, este servicio será responsable de enviar solicitudes HTTP al API de de explorar lugares de Foursquare. Para más información acerca de API para explorar lugares Foursquare  y cómo podemos obtener yo propio clientID y clientSecret puedes revisar la documentación oficial de Foursquare.


Abre el archivo y escribe el siguiente código:


Por lo visto en el código anterior notarás que se ha creado un simple factory, todo lo que se tiene que hacer es llamar a la función app.factory() donde app es una variable compartida declarado en el archivo app.js archivo que contiene  nuevo módulo “FotosLugaresApp”.
Bien notarás que hemos inyectado un servicio AngularJS bluid-in llamado “$resource” dentro de nuestro servicio, este servicio no trabaja hasta nosotros inyectemos el módulo “ngResource”  a nuestro modulo “FotosLugaresApp”, esto hecho en el archivo app.js.
Básicamente el recurso construido $resource es un servicio el cual nos permite interactuar con fuentes de datos  RESTful, podemos usar otros servicios built-in de bajo nivel llamado $http, pero en nuestro caso el servicio $resource  es suficiente.
Ahora necesitamos configurar el servicio $resource pasando los parámetros necesarios para API de explorar los lugares  de FourSquare, puedes revisar los parámetros necesarios visitando su documentación, los que vale mencionar aquí es que el parámetro :action será traducido a una parte de la URL y cualquier otro parámetro será trasladado como cadenas de consulta pares(key,values). Seguro necesitamos parámetros extras para pasar esto a la API, así como cerca  de ciudad y categoría para explorar. Estos parámetro serán enviados desde el  controlador, ya veremos pronto esto.Nota: puedes usar estos clientID y Secret para seguir  este aplicación demo, pero recomiendo tener tu propio clientID y Secret.
No olvides referenciar el archivo JS creado en la parte inferior de nuestra página principal HTML(index.html).


Paso 2: Implementado Lógica de Negocios en Nuestro Controlador.
Ahora empezaremos a implementar las funciones y modelos necesarios para interactuar con nuestra vista “resultadolugares.html”, si estás siguiendo del post anterior, nosotros hemos creado un controlador llamado “lugarExplorarController” con un simple modelo (explorarCerca), ahora necesitamos expandir los modelos y funciones para construir la aplicación, se ha escrito el siguiente código  en el controlador y se explicara  que se está haciendo en el siguiente párrafo:


  • Hemos estado inyectando “explorarLugarServices” y otro servicio construido (built-in) llamado “$filter” al controlador
  • Hemos definido diferentes objetos modelos(exploraCerca, exploraConsulta, array de lugares, etc.) donde ellos serán usados para en enlace de datos bidireccional entre nuestra vista “resultadoLugares.html” y el modelo.
  • Después inyectamos el servicio “explorarLugarServices” como se muestra en el siguiente código:
  • Fuimos capaces de emitir solicitud HTTP GET para el factory que hemos creado, nota como podemos pasar cualquier número de argumentos al método get, y todos eso argumentos( es decir near, query, limit , etc) seran trasladado a la consulta string par (key,value), por tener esto pudimos tener una solicitud GET completa con los parámetros necesarios para la paginación del lado del servidor.
  • Hemos usado un filtro personalizado el cual nos permite filtrar los resultados retornados, cubriremos cómo crear filtros pronto.
  • Hemos creado un reloj para “filterValue”, en simples palabras hemos agregado un escucha para el atributo “filterValue” de $scope, este escucha es lanzado cuando el valor de este atributo ha cambiado.
  • Hemos agregado diferentes funciones necesarias para ser llamadas de la vista, así como “hacerBusqueda()” el cual será llamado dentro del click del botón Explorar, también  “PaginaCambiada()” el cual será llamado desde la página en el cambio del control de paginación.
  • Múltiples funciones de ayuda han sido agregados, estas funciones son usadas para construir una fuente de imágenes thumbnails(miniaturas).


Ahora necesitamos agregar filtro el cual permitirá a los usuarios filtrar resultados retornados, estaremos filtrando por nombre de lugar, categoría de lugar.


Paso 3: Agregando filtro personalizado
Para definir un filtro personalizado necesitamos agregar un nuevo archivo JS llamado “LugarNombreCategoriaFilter.js” a la carpeta “app->filters”, abre el archivo y escribe el siguiente código:


Definiendo un filtro es sencillo y es como definir un factory, todos necesitamos hacer este llamado a la función app.filter() dónde “app” es una variable compartido declarada en el archivo app.js el cual contiene nuestro módulo “FotosLugaresApp”. podemos inyectar servicios en los filtros pero en nuestro caso el filtro es simple, este aceptará un arreglo de los lugares retornado del API Foursquare, y valor del filtro, entonces esto filtró el arreglo de lugares solamente por el nombre o la categoría, el resultado de este proceso es un nuevo array de lugares filtrado.
Para usar este filtro personalizado en “lugarExplorarController” es simple, necesitamos inyectar el servicio construido “$filter”, entonces somos capaces de ejecutar nuestro filtro personalizado llamando:


Paso 4: Modificando la vista “resultadolugares.html”
Hasta este punto ya tenemos el servicio y controlador, pero necesitamos trabajar en la vista con el fin de proyectar los resultados de una manera agradable y permitiendo la entrada del usuario desde la vista al servicio, entonces vamos a abrir la vista “resultadolugares.html” y escribir el siguiente código:


Debajo está una explicación de que se ha hecho en esta vista:
  • Hemos usado ng-model con el modelo “exploraCerca” y “exploraConsulta”, una vez que cambiamos el texto en los campos de entrada, el modelo se actualizará directamente.
  • Hemos enlazado el evento click del botón “Explorar”, con la función “hacerBusqueda” en el controlador, usando la directiva ng-click.
  • Hemos usado ng-repeat para iterar el array de lugares filtrados entonces podemos enlazar la vista con cada lugar, note como creamos la etiqueta <li> por cada lugar.


  • Dentro de ng-repeat hemos sido capaz de incluir el dato de un solo lugar e imprimir o en la vista, form ejemplo para imprimir  el nombre hemos usado {{item.venue.name}}, tambien hemos sido capaz de executar la funcion de la simple manera : ng-src=”{{builCateroriaIcono(item.venue.categories[0].icon)}}.
  • hemos usado el filtro construido de AngularJS para formatear el número decimal {{item.venue.rating | number:1}}, puedes encontrar mas información de filtros construidos aqui.
  • Hemos implementado paginación usando AngularJS Bootstrap UI directiva llamada “data-pagination”, usando esto hemos sido capaz de implementar paginación del lado del servidor. Este control de paginación  es flexible. puedes revisar cómo personalizarlo aquí.
  • Hemos agregado un enlace con el título “Bookmark Lugar” el cual será usado para guardar los lugares favoritos del usuario, implementaremos la función “bookmarkLugar()” en el siguiente post.


Lo que queda es mostrar la 9 images pequeñas en la parte de adelante cuando el usuario haga clic en el nombre del lugar, una buena manera para implementar esto es usando el servicio $modal el cual nos permite abrir diálogos modales delante de nuestra página de  resultado de búsqueda, en el siguiente paso agregaremos esta ventana modal.


Paso 5: Agregando una vista modal a la vista de imágenes de lugares
  • La vista modal es una vista normal html, así que vamos agregar un nuevo archivo llamado “fotosLugares.html” dentro de “app->views”, abre el archivo y escribe el siguiente código:


Para obtener las imágenes, necesitamos hacer una solicitud GET HTTP al API de Foursquare, esta llamada es idéntica a lo realizado previamente(explorarLugarService.js), entonces lo que necesitamos es crear un nuevo servicio llamado “fotosLugaresService” el cual será responsable de emitir esta solicitud GET. así que vamos a crear el archivo llamado  “fotosLugaresService” dentro de la carpeta “app->services”, abrimos el archivo y escribimos el siguiente código:


Como mencionamos temprano cada vista tiene su único controlador, así que necesitamos crear un nuevo controlador llamado “fotosLugaresController”, entonce agregamos un nuevo archivo JS llamado “fotosLugaresController.js” dentro de la carpeta “app->controllers”, abres el archivo y escribes el siguiente código:




Hasta este momento AngularJS no es consciente  que la nueva vista y controlador creados están atados juntos, previamente hicimos esto usando $routeProvider mientras arrancamos nuestra aplicación, pero en este caso estamos usando el servicio $modal nosotros podemos informar a AngularJS de esta relación una vez iniciamos el modal, recordemos que queremos mostrar la vista como un modal no como una vista parcial, incluir el siguiente fragmento de código dentro “lugarExplorarController”:


Por lo visto en el código anterior, notarás que hemos inyectado el nuevo servicio “fotosLugaresService” en el controlador, así que podemos emitir una solicitud GET HTTP, también hemos inyectado el servicio $modal el cual será responsable de abrir del diálogo modal. Una vez  que recibimos las 9 imágenes pequeñas satisfactoriamente  del API, llamaremos a $modal.open e inyectamos el template URL, y el controlador en la sección configuración, una vez hecho esto AngularJS será consciente  que el template es mapeado a este controlador. también hemos pasado el nombre del lugar y el arreglo de 9 fotos pequeñas al controlador “fotosLugaresController”. El resultado final se muestra a continuación:
Si revisamos nuestro proyecto la estructura de archivos estaría de la siguiente manera:

En el siguiente post agregaremos la última funcionalidad a nuestra aplicación el cual permitirá al usuario bookmark para sus lugares favoritos.

TUT: AngularJS Parte 2 de 12: Enlace de Datos en AngularJS

Introducción
En la entrada anterior Angular parte 1 de 12: Introducción a AngularJS, hemos visto un material introductorio y pocas directivas con ayuda de un ejemplo de aplicación para entender lo básico de AngularJS. Pienso que estamos ya algo familiarizado con AngularJS y ahora es tiempo de ir más en esto. vamos a proceder con esta parte del tutorial donde nosotros trataremos de entender la característica más básica e impresionante de AngularJS es decir Enlace de Datos(data binding).

Antecedentes
Enlace de datos o Data Binding es la más útil y poderosa característica  entre los existentes y próximas tecnologías de desarrollo de software. Actualmente es un proceso que tiende un  puente de conexión entre  la vista y la lógica de negocios de la aplicación.
Básicamente vemos una manera y dos maneras  de enlace de datos con respecto a aplicaciones AngulasJS. Pero antes vamos a saltar a esta sección para entender algunas cosas acerca de la variable $scope en AngulasJS.

$scopes en el mundo de AngularJS
Primero vamos a tratar de entender $scope. Deje este tema en nuestro post anterior, así que vamos a continuar con esto porque .tiene mucho que ver con aplicaciones AngujarJS. $scope son lo principal en cualquier aplicación AngularJS. Ya que se utilizan en todas las aplicaciones AngularJS. En AngularJS, $scope son esos objetos que contienen funcionalidad y los datos que tienen serán presentados en la vista. $scope en la aplicación representan al modelo de la aplicación, así se puede pensar los scope como un view model.
Scopes son la fuente de para el estado de la aplicación, porque de esto vive binding, podemos confiar en $scope para actualizar  inmediatamente cuando la vista los modifica y podemos confiar en la vista para actualizar cuando $scope cambia.

Funciones de $scope
  1. Provee observadores para mirar todos los cambios del modelo.
  2. Provee  la habilidad de propagar los cambios del modelo aunque la aplicación esté fuera del sistema a otros componentes asociados.
  3. $scope puede ser anidado de tal manera que pueden aislar funcionalidad y propiedades de modelo.
  4. Provee un entorno de ejecución dentro del cual las expresiones son evaluadas.

Básico de Data Binding/ enlazar datos unidireccionales
El enlace de datos unidireccional es un enfoque donde un valor es tomado del modelo de datos e insertado a un elemento HTML.  no hay manera de actualizar el modelo de la vista.
AngularJS provee algunos directivas data binding predefinidas los cuales se mencionan a continuación:
ng-bind: Enlaza a la propiedad interna Text de un elemento HTML.
ng-bind-template: Casi similar a la directiva ng-bind pero permitido para múltiples plantillas.
ng-non-bindable: Declara una region de contenido para el cual en enlace de datos será saltado.
ng-bind-html: Crea enlace de datos usando la propiedad interna HTML de un elemento HTML.
ng-model: crea un enlace de datos bidireccional.


Vamos a tratar de entender algunas de las directivas programáticamente, el cual te mostrará cómo puede usarse en nuestra aplicación dentro de un escenario real. He creado un módulo en el post anterior y estoy usando los mismo y también voy a  extender el controlador de la misma.


Ahora este es nuestro archivo app.js


Debajo nuestro maincontroller.js y nombrado como “BookStore”


Y aquí llega nuestra pagina html el cual mostrará en el navegador.


En el ejemplo anterior muestra acerca de 2 directivas los cuales son usados para enlace de datos ng-bind y ng-non-bindable. también veremos ng-model en la siguiente sección cuando hablemos acerca enlace de datos bidireccional  en AngularJS. No he usado ng-bind-template ni ng-bind-html pero vamos a entrar en ello cuando lleguemos a aprender  plantillas en AngularJS.
Este es la salida final  cuando se ejecuta index.html, como se muestra para el estilo de la página se está utilizando BootStrap(http://getbootstrap.com/getting-started/#download).
De la salida podemos ver  que cuando usamos {{ }} la salida es un resultado esperado que AngularJS usa para manejar el enlace de datos al modelo. La segunda sección usamos la directiva ng-bind y en la tercera hemos usado ng-non-bindable, el cual nos permite saltarnos el enlace de datos en esta sección en particular en la que se define. También está la directiva ng-repeat el cual nos ayuda a iterar la colección. La colección que usamos puede ser implementado con la ayuda de algunas llamadas de Web-Api, los cuales proveerán algunos datos JSON que se puede directamente usar en el enlace.


Enlace de datos Bidireccional
En simples términos el enlace de datos bidireccional es cuando el modelo cambia, la vista refleja los cambios y viceversa. El enlace de datos bidireccional en AngularJS son creados con la directiva ng-model. Prácticamente, enlace de datos bidireccional puede ser aplicado solo a esos elementos que permite al usuario proveer un valor de datos, lo que significa la entrada de datos a través de elementos de formularios como input, textarea, y elementos seleccionado.
Vamos ahora a tratar de ver como podemos implementar el enlace de datos bidireccional en cualquier aplicación. Agregamos una nueva página html y agregamos el siguiente código:


Ahora extendemos nuestro controlador e implementamos algunas funcionalidades para mostrar los item en la tabla y permitir a los usuarios editar, guardar y eliminar los datos en la tabla. Desde esta aplicación no estamos usando ni un Web Service ni un Web API para enviar datos al servidor a través de alguna solicitud Ajax. A medida que avanzamos vamos a tratar de entender la aplicación que usa algunas Web API para enviar datos al servidor.


La salida en el explorador seria:
Ahora vamos agregar una función, a nuestro controlador “BookStore”, para agregar una colección de Items de la vista a nuestra tabla.
Para usar la funcionalidad necesitamos algo para el ingreso del usuario. Así que añadiremos etiquetas html para el ingreso. como podemos ver  se ha usado ng-model=”item.ISBN” y esto actualmente provee enlace de datos bidireccional para facilitarnos.


Ahora estamos listos con el código. es tiempo de ver el final de nuestra aplicación. Aqui esta el resultado de realizar operaciones CRUD( Create, Read, Update and Delete).


Nota: No hay validaciones o chequeo de errores. Esto lo he hecho intencionalmente porque esto lo vamos a ver cuando revisemos validaciones en en un post más adelante en AngularJS.


Puntos Interesantes
Ahora conocemos el enfoque de enlace de datos o Data Binding que AngularJS sigue y hemos visto en la aplicación de ejemplo que podemos implementar en la aplicación para la realizacion de operaciones basica CRUD.
En las siguientes parte de la serie de tutoriales podremos estar aprendiendo:

  • Parte 3 de 12: Eventos en Angular
  • Parte 4 de 12: Validación
  • Parte 5 de 12: Serialización
  • Parte 6 de 12: Plantillas
  • Parte 7 de 12: Módulos
  • Parte 8 de 12: Inyección de Dependencias
  • Parte 9 de 12: Testeo Automatizado
  • Parte 10 de 12: SPA Ruteo/Historia
  • Parte 11 de 12: Directivas-una característica que AngularJS provee
  • Parte 12 de 12: Integración CSS para crear interfaces amigables.