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.