Es un momento grandioso para ser un developer de JavaScript. Los frameworks modernos de JavaScript como Backbone, Knockout, AngularJs y demás, han llevado a un nivel de madurez y sofisticación la creación de aplicaciones web enriquecidas basadas en HTML que habían sido muy solicitadas. Estos frameworks tienen un objetivo en común: hacer simple para los desarrolladores la construcción de aplicaciones robustas con HTML, CSS y JavaScript.

Este tutorial explora el framework AngularJs de Google. Comenzaremos describiendo la filosofía de diseño usada en este framework y después desarrollaremos una simple pero no trivial aplicación para demostrar los fundamentos de AngularJs así como sus características principales incluidas data binding, dependency injection, loosely coupled code y conciseness.

AngularJS-large

Nota: Puedes seguir el tutorial usando los links de Plunker. Plunker es una herramienta de generación de prototipos para HTML, CSS y JavaScript. Si prefieres editar tus archivos localmente puedes descargar el archivo zip con el código GettingStartedWithAngularJS.zip

La filosofía de AngularJS

La filosofía de AngularJS esta basada en mejorar y extender HTML entendiendo las necesidades tanto de los nuevos como de los ya experimentados desarrolladores.

HTML mejorado

HTML es muy bueno para describir documentos estáticos, pero se queda corto cuando se trata de describir las “vistas” de una aplicación web enriquecida pues no es algo para lo cual haya sido diseñado HTML. La mayoría de los frameworks de JavaScript abstraen esta limitación separando la descripción de las vistas del HTML o usan archivos bastante largos de JavaScript para manipular el DOM (Document Object Model). AngularJs toma esto desde una perspectiva diferente. En lugar de ocultar el HTML y el CSS, toma sus fortalezas y las extiende volviendolas adecuadas para la descripción de vistas dinámicas. El resultado es un flujo de trabajo que resulta bastante familiar para cualquier desarrollador web y con un estilo de programación de JavaScript sorprendentemente conciso, claro y enfocado.

Simple pero escalable

Otra característica que distingue a AngularJs, es que es de fácil comprensión para los que comienzan a usarlo pues ofrece caracteristicas sofiticadas para desarrolladores con necesidades complejas. Otros frameworks se enfocan en la simplicidad sin proveer mucha asistencia para crear aplicaciones complejas u ofrecen características sofisticadas que requieren muchas plantillas de código y mover muchas partes de ellas incluso para aplicaciones simples.

Los bloques de AngularJs

El código de aplicaciones creadas con AngularJs siempre esta organizado Modelos, Vistas, Controladores y (opcionalmente) Servicios.

Los Modelos, son objetos que representan los datos a los cuales puede acceder la aplicación. Los Modelos también son usados para representar el estado actual de la aplicación.

Los Controladores, definen el comportamiento actual de la aplicación (también conocido como “la lógica de la aplicación”) y juega un rol clave conectando los modelos con las vistas.

Los Servicios, son objetos especializados que realizan el trabajo en nombre de otros objetos. Los servicios tienen varios usos, desde traer datos remotos hasta proveer e implementar algún algoritmo. Se busca que los Servicios sean altamente reusables y son diseñados para ser intercambiados fácilmente por otros servicios similares.

Hasta este punto toda este panorama de la filosofía y arquitectura probablemente parecerá muy abstracto, pero ahora que ya conoces un poco más de la teoría estas listo para entrar a la práctica y construir una aplicación.

Construyendo una app

Vamos a desarrollar una aplicación que busque fotografías con AngularJS. Podrás ver la aplicación final aquí. Para probar la aplicación escribe alguna palabra en el cuadro de búsqueda en la esquina superior izquierda y pulsa el botón “Find”. Podrás elegir entre miniaturas pequeñas o grandes haciendo click en los botones de la esquina superior derecha.

Conforme vayas avanzando irás descubriendo links hacia Plunk o “plunks” (código en línea editable) que podrás usar en cada paso. Para continuar visita el url de Plunk y da click en el botón “Fork” para crear tu copia y trabajar desde ella.

El primer paso es algo a lo que ya deberías de estar muy acostumbrado: maquetar tu aplicación usando HTML y CSS. Toma un momento para revisar el HTML seleccionado Source Code > index.html (Puedes ver este plunk aquí).

Agregando AngularJS

Ya con la estructura básica maquetada es momento de configurar AngularJs:

1.- Abre el plunk Photo App y haz click en Fork para usarlo como base.También puedes descargar los archivos y trabajar localmente.
2.- Agrega la siguiente etiqueta al final de la página justo antes de la etiqueta de cierre </body>

<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.0.4/angular.min.js"></script>

Necesitarás indicarle al framework que trate la página como una aplicación AngularJs

3.- Agrega la directiva ng-app a la etiqueta de <body> de la siguiente forma:

<body ng-app>

Las directivas son la manera en como AngularJS extiende el HTML para hacerlo un leguaje de plantillas más adecuado para interfaces de usuarios enriquecidas. Aprenderas sobre la variedad de directivas conforme vayas avanzando.

Introducción a data binding

El data binding es una de las características más poderosas de AngularJs. Data binding es una elegante solución para una de las tareas más complejas de construir una aplicación web enriquecida: mantener múltiples datos en sincronía. Esta aplicación hace un fuerte uso del data binding. Integremos data binding con los siguientes pasos para mejorar la interfaz del usuario.

1.- Ubica el elemento de formulario search-field:

<form class="search-field">
<input type="text">
<input type="submit" value="Find">
<span class="search-message">photos of water</span>
</form>

2.- Agrega la directiva ng-model=”searchKeyword” al textinput:

<input type="text" ng-model="searchKeyword">

La directiva ng-model le dirá a AngularJS que quieres ligar el valor del campo de texto a una variable del modelo llamada searchKeyword. Con esta ligadura, siempre que el usuario edite el campo de texto, la variable searchKeyword será actualizada automáticamente.

3.- Reemplaza el texto “photos of water” por “photos of {{searchKeyword}}”:

<span class="search-message">photos of {{searchKeyword}}</span>

La notación de las dobles llaves es otra forma de declarar el data binding. La expresión dentro de las llaves será evaluada y actualizada cada vez que el valor en dicha expresión cambie.

La versión actualizada de la aplicación puedes verla aquí. Escribe algún texto en el campo de texto para ver esta mejora en acción.

La siguiente mejora usará data binding para reemplazar la lista actual de imagenes que estan en código duro (“hardcodeadas”) en el HTML. Primero necesitaremos crear un controlador.

Introducción a los Controladores

Como habrás notado anteriormente, los controladores juegan un rol clave ligando objetos en la aplicación. Las mayoría de las aplicaciones del mundo real pueden tener muchos controladores, incluyendo un controlador para cada pantalla de la aplicación e inclusive controladores para cada componente de la interfaz de usuario. La aplicación en la que estamos trabajando solo necesita un solo controlador. Lo llamaremos “MainController”.

Nota: Si lo prefieres, puedes continuar editando el proyecto en el que estas trabajando o puedes abrir el plunk Photo App – Step 1 y hacer click en “Fork” para usarlo como base para continuar.

1.- Crea un nuevo archivo de JavaScript con el nombre MainController.js (Para crear el archivo en Plunk, haz click en +New en la sección Files en la esquina superior izquierda.)

Nota: Crear archivos separados .js no es un requerimiento de AngularJS, pero es una buena práctica y técnica para administrar nuestro código, principalmente cuando trabajamos en equipo con otros desarrolladores.

2.- Agrega el siguiente código al archivo que acabas de crear:

function MainController($scope) {
'use strict'?
$scope.photos = [
{ title: 'Photo 1', thumbUrl: '//googledrive.com/host/0Bz6MIjSA3u5MSDNwcmNDYWVOdms/images/mountains1.jpg'},
{ title: 'Photo 2', thumbUrl: '//googledrive.com/host/0Bz6MIjSA3u5MSDNwcmNDYWVOdms/images/mountains2.jpg'},
{ title: 'Photo 3', thumbUrl: '//googledrive.com/host/0Bz6MIjSA3u5MSDNwcmNDYWVOdms/images/mountains3.jpg'}
]?
}

Los controladores en AngularJS son declarados en el constructor como se muestra en el código anterior. Una de las responsabilidades del controlador en AngularJS es configurar cualquier modelo para que el controlador de la vista asociada pueda tener acceso. El objeto del modelo puede ser cualquier tipo de objeto de JavaScript, desde una simple cadena de texto o un número hasta un objeto complejo personalizado. El código que agregamos define el modelo photos, el cual es un arreglo de objetos que describe cada foto a mostrar.

Seguramente estarás preguntándote cual es la historia detrás del argumento $scope. ¿Qué es?, ¿De dónde viene? $scope es un objeto especial que se pasa a la función del controlador por AngularJS. Sirve de puente entre el controlador y la vista y es uno de los más importantes tipos de objetos que se usan en AngularJS. Cualquier propiedad que agregues a $scope se podrá acceder directamente a ella desde la vista, naturalmente es el lugar perfecto para alamacenar las referencias a tu modelo(como se hace en el código anterior con photos).

Tienes ahora dos pequeños cambios que realizar antes de tomar ventaja del nuevo modelo. Primero habrá que ligar el archivo MainController.js a la página index.html

3.- Agrega la etiqueta <script src="MainController.js"> justo debajo de la referencia a angular.js

<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.0.4/angular.min.js"></script>
<script src="MainController.js"></script>

Finalmente necesitas indicarle a AngularJS que parte de la vista está asociada a MainController. Dado que esta aplicación solo tiene un controlador, podremos asociar la etiqueta <div> principal con el MainControlles usando la directiva ng-controller.

4.- Agrega ngcontroller="MainController" a la etiqueta <div> en la linea 13:

<div ng-controller="MainController">

Ahora cada elemento HTML dentro de la etiqueta <div> tiene acceso directo al modelo de fotos. Ahora sacaremos provecho en la siguiente mejora.

Declarando elementos repetidos del UI

Ahora reemplacemos los tres elementos de la lista:

1.- En index.html, elimina los elementos <li> excepto el primero:
<li>
<img src="http://googledrive.com/host/0Bz6MIjSA3u5MSDNwcmNDYWVOdms/images/ocean1.jpg"/>
<p class="title">Photo Title</p>
</li>

2.- Hagamos los siguientes cambios al código anterior:

<li ng-repeat="photo in photos">
<img ng-src="{{photo.thumbUrl}}"/>
<p class="title">{{photo.title}}</p>
</li>

Este código usa la directiva ng-repeat para indicarle a AngularJS que genere un <li> por cada objeto en el modelo photos. Cada <li> usa la misma notación de data binding vista anteriormente para ligar las propiedades thumbUrl y title a cada objeto de photo. Podrás notar como se cambia el atributo src de la etiqueta <img> por la directiva ng-src puesto que es necesario para poder usar el valor del data binding como valor para el atributo de la etiqueta.

La versión actualizada de la aplicación puedes visualizarla aqui. Podrás darte cuenta que el resultado de la lista es ahora una representación dinámica del modelo photos.

Ahora que la relación entre la vista el modelo photos esta establecida ya se podemos agregar comportamiento a la aplicación.

Definiendo el comportamiento

Para hacer accesible los modelos hacia las vistas, el otro rol clave de un controlador es definir la lógica de nuestra aplicación rápidamente. Un controlador puede lograr esto implementando una interfaz de JavaScript que la vista pueda llamar a través de ciertas acciones de la aplicación. Este concepto se ilustra implementando los botones “Small” y “Large” que cambian de tamaño las fotos.

Nota: Podrás continuar editando tu proyecto o abrir el plunk Photo App – Step 2 y hacer click en “Fork” para usarlo de base y poder continuar.

Necesitaras una forma de dar seguimiento a las acciones que elija el usuario sobre ver grandes o pequeñas las fotos. Esto suena a un trabajo del modelo.

1.- Agrega la siguiente línea de código a MainController.js justo después de la declaración del modelo photos para establecer el modelo thumbSize:

$scope.thumbSize = 'small'?

Ya mencione que el controlador debe proveer una interfaz JavaScript que la vista pueda invocar. El forma de hacer esto es usando nuevamente el objeto $scope como puente. Cualquier función que se declare dentro del objeto $scope podrá ser llamada directamente desde la vista.

2.- Dabajo de $scope.thumbSize = 'small'; agrega una función al controlador para gestionar el tamaño de las fotos:

$scope.setThumbSize = function(size) {
$scope.thumbSize = size?
}?

3.- Regresa a index.html

Uno de los roles de las vistas es convertir las interacciones del usuario en acciones de la aplicación. Para esta app convertiremos la interacción de pulsar el botón para cambiar de tamaño las imágenes en una acción llamada setThumbSize().

4.- Para lograrlo, agrega la directiva bg-click a cada botón.

<div class="size-controls btn-group">
<button ng-click="setThumbSize('small')">Small</button>
<button ng-click="setThumbSize('large')">Large</button>
</div>

5.- Puedes deshabilitar el botón correspondiente al tamaño de la imagen con la directiva ng-disabled y un binding.

<div class="size-controls btn-group">
<button ng-disabled="thumbSize == 'small'"
ng-click="setThumbSize('small')">Small</button>
<button ng-disabled="thumbSize == 'large'"
ng-click="setThumbSize('large')">Large</button>
</div>

Ahora pulsa los botones de “Small” y “Large” y veras como deshabilitan de manera adecuada. Ahora necesitarás modificar las fotos acorde al botón seleccionado.(Nota: para ejecutar el código con Plunker, haz click en el icono con el ojo ubicado en la barra de herramientas, el cual mostrará el preview panel con el resultado final).

En la vista, el tamaño de la miniatura se establece aplicando el estilo “small-thumbs” o “large-thumbs” a “results-list”. Estas clases fueron definidas previamente en el archivo photo-app.css.

Se pueden aplicar clases dinámicamente con AngularJS usando la directiva “ngclass”

6.- En el elemento <ul>, cambia ‘class=”results-list small-thumbs”‘ por ‘class=”results-list” ng-class=”thumbSize + ‘-thumbs'”‘:

<ul class="results-list" ng-class="thumbSize + '-thumbs'">
<li ng-repeat="photo in photos">
<img ng-src="{{photo.thumbUrl}}"/>
<p class="title">{{photo.title}}</p>
</li>
</ul>

Con esa modificación final el comportamiento de selección de tamaño de la miniatura está completo. Puedes verlo en acción en la versión actualizada aquí).

Ahora estás listo para la última pero más importante característica de tu aplicación, el comportamiento de la búsqueda de fotos.

Introducción a Servicios

En AngularJS, los servicios son objetos especiales que registras con el framework para poder ser llamados por otros objetos, usualmente controladores, para realizar ciertas funciones. Deberás encapsular la lógica de la búsqueda de fotos de la aplicación en un objeto de servicio llamado “photoSearch”. Pero antes de poder hacer eso, necesitas establecer un módulo a la aplicación.

En la comunidad de javascript, el significado del término módulo varía dependiendo del contexto en el que se hable de él. En AngularJS el término módulo se refiere al mecanismo específico para agrupar y configurar objetos en tu aplicación. Esto incluye a los objetos de servicio, así que para crear el servicio “photoSearch” debes comenzar declarando un módulo de alto nivel para la aplicación y llamarlo photoApp.

Nota: Puedes abrir Photo App – Step 3 plunk y dar click en Fork para usarlo como tu punto de inicio, o simplemente seguir editando los archivos de la sección anterior.

1.- Crea un nuevo archivo llamado photoApp.js
2.- Agrega el siguiente código a el:

angular.module("photoApp", []);

Sencillo ¿No? De hecho, debes estar preguntándote por qué está en su propio archivo .js. En la mayoría de aplicaciones reales, el módulo de alto nivel requerirá de una configuración más compleja, incluyendo la declaración de rutas (URLs que mapean a estados o vistas) y parámetros de URL que tu aplicación acepte. Por esto, es útil separar la definición del módulo en su propio archivo .js para tener claro su rol como configuración.

3.-Para usar el nuevo módulo necesitas hacer 2 pequeños cambios al index.html. Primero, añade una nueva etiqueta <script> para cargar el nuevo archivo photoApp.js:

<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.0.4/angular.min.js"></script>
<script src="MainController.js"></script>
<script src="photoApp.js"></script>

4.- Ahora, debes indicarle a AngularJS cómo debe de tratar “photoApp” como el módulo de alto nivel; modificando la directiva ng-app como se indica a continuación:

<body ng-app="photoApp">

5.- Con el módulo en su lugar, ahora puedes definir el servicio “photoSearch”. Crea un nuevo archivo llamado photoSearchService.js.
Antes de añadir el código completo, observa el esqueleto de sus características clave para ver como funcionan los servicios.

angular.module('photoApp').factory('photoSearchService', function() {
var service = {};
/**
@param keyword - The keyword to search for.
@param callback - A function to call when the search is complete.
The function will be passed a single argument which is an array of photo items matching the keyword.
*/
service.findPhotos = function(keyword, callback) {
...
};

return service;
});

Primero, el código obtiene la referencia al módulo de alto nivel de la aplicación usando “angular.module(‘photoApp’)”. Después, registra el servicio llamando al método “factory(” en ese módulo. El primer parámetro es el nombre que quieras darle al servicio. El segundo parámetro es una función factory. “Factory” es solo una etiqueta que se le da a cualquier función que regresa una nueva instancia de un objeto. En este caso, se espera que la función factory regrese un nuevo objeto que pueda ser usado como una instancia de “photoSearchService”. Puedes ver que “photoSearchService” consta de un solo método llamado “findPhotos()”, que busca fotos basado en una palabra clave y ejecuta una función de callback pasando con ella los resultados.
Es importante aprender el patrón general mostrado arriba para escribir un servicio y registrarlo con tu aplicación. Los detalles de implementación reales del método “findPhotos()”, que están a punto de ver, no son importantes. Es más, no es nada práctica la implementación que usa resultados predefinidos y únicamente soporta dos términos de búsqueda “water” y “montañas”. Se plantea esta implementación porque es simple y funciona lo suficientemente bien para producir una aplicación completa y funcional, lo cual es el objetivo de este artículo.

6.- Añade el siguiente código al archivo photoSearchService.js:

angular.module('photoApp').factory('photoSearchService', function() {

‘use strict’;

var service = {};

/**
@param keyword – The keyword to search for.
@param callback – A function to call when the search is complete. The function
will be passed a single argument which is an array of photo items matching the
keyword.
*/
service.findPhotos = function(keyword, callback) {

// For simplicity we’re hard coding the results for the
// two supported search terms, “water” and “mountains”.
var matches = [];

if (keyword.toLowerCase() === ‘water’) {
matches = [
{
title: ‘A Perfect Morning’,
thumbUrl: ‘http://googledrive.com/host/0Bz6MIjSA3u5MSDNwcmNDYWVOdms/images/water1.jpg’
},
{
title: ‘Footprints’,
thumbUrl: ‘ http://googledrive.com/host/0Bz6MIjSA3u5MSDNwcmNDYWVOdms/images/water2.jpg’
},
{
title: ‘Rush (II)’,
thumbUrl: ‘http://googledrive.com/host/0Bz6MIjSA3u5MSDNwcmNDYWVOdms/images/water3.jpg’
},
{
title: ‘El Matador State Beach’,
thumbUrl: ‘http://googledrive.com/host/0Bz6MIjSA3u5MSDNwcmNDYWVOdms/images/water4.jpg’
},
{
title: ‘El Matador State Beach’,
thumbUrl: ‘http://googledrive.com/host/0Bz6MIjSA3u5MSDNwcmNDYWVOdms/images/water5.jpg’
},
{
title: ‘Big Sur’,
thumbUrl: ‘http://googledrive.com/host/0Bz6MIjSA3u5MSDNwcmNDYWVOdms/images/water6.jpg’
}];
} else if (keyword.toLowerCase() === ‘mountains’) {
matches = [
{
title: ‘Difficult Roads’,
thumbUrl: ‘http://googledrive.com/host/0Bz6MIjSA3u5MSDNwcmNDYWVOdms/images/mountains1.jpg’
},
{
title: ‘Klondike Highway – Mountain’,
thumbUrl: ‘http://googledrive.com/host/0Bz6MIjSA3u5MSDNwcmNDYWVOdms/images/mountains2.jpg’
},
{
title: ‘Mount Ossa and Cathedral Mountain’,
thumbUrl: ‘http://googledrive.com/host/0Bz6MIjSA3u5MSDNwcmNDYWVOdms/images/mountains3.jpg’
},
{
title: ‘Heading Down the Mountain’,
thumbUrl: ‘http://googledrive.com/host/0Bz6MIjSA3u5MSDNwcmNDYWVOdms/images/mountains4.jpg’
},
{
title: ‘Stone Bridge’,
thumbUrl: ‘http://googledrive.com/host/0Bz6MIjSA3u5MSDNwcmNDYWVOdms/images/mountains5.jpg’
}
];
}

callback(matches);
};

return service;

});

7.- Agrega este script al índice:

<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.0.4/angular.min.js"></script>
<script src="MainController.js"></script>
<script src="photoApp.js"></script>
<script src="photoSearchService.js"></script>

Ahora que la configuración básica de “photoSearchService” está terminada, necesitas una forma de que MainController aproveche este servicio. Para lo cual puedes utilizar inyección de dependencias.

Introducción a inyección de dependencias

Cuando un objeto necesita llamar a otro para que realice su trabajo, se dice que el primer objeto es dependiente al segundo.
Las dependencias—objetos colaborando con otros—son las que hacen posibles las aplicaciones modernas y complejas. Pero también la dependencia presenta un reto. Puedes adaptar la dependencia entre dos objetos incluyendo una referencia escrita deñ primer al segundo objeto, pero eso resulta en código no escalable. Esto es malo por varias razones. Hace los objetos y funciones muy difíciles de probar de manera aislada. Hace el código frágil y resistente al cambio. Limita tu habilidad para reutilizar objetos o cambiarlos en implementaciones alternativas. La lista sigue y sigue.

El patrón de diseño de inyección de dependencias surgió para encarar este reto, y el soporte de inyección de dependencias de AngularJS es una de sus principales características. Como verás, inyección de dependencias es un término extravangante para una técnica sencilla. En el caso de un controlador, la forma de evadir dependencias de código estático al pedir a AngularJS que provea las dependencias del controlador como parámetros al constructor de este. Puedes realizar esto simplemente especificando nombres de parámetros que AngularJS pueda reconocer.

Aunque probablemente no lo hayas notado, arriba te beneficiaste de la inyección de dependencias en MainController. Su referencia al objeto $scope está proporcionada por inyección de dependencias. Pero $scope no es la única dependencia que puedes pedirle al framework. Como ejemplo, si aparte de $scope quisieras pedirle a AngularJS un objeto que pueda proporcionar acceso a cualquier parámetro especial que sea parte de la URL actual puedes solicitar el objeto $routeParams así:

function MainController($scope, $routeParams) { … }

Puedes encontrar muchas más objetos inyectables útiles listados en la documentación del API de AngularJS. El orden de los parámetros no es importante; los nombres lo son. El nombre de cada parámetro es la forma en que AngularJS reconoce qué objeto está pidiendo el controlador.

Con este conocimiento básico de inyección de dependencias de AngularJS, estás listo para integrar “photoSearchService” a “MainController”.

1.- Añade “photoSearchService” a los parámetros de la función “MainController” en MainController.js:

function MainController($scope, photoSearchService) {

2.- Borra los datos de fotos estáticos borrando de la línea 6 a la 8:

$scope.photos = [];

3.- Ahora, añade el siguiente método a $scope justo después del método setThumbnailSize():

$scope.submitSearch = function() {

$scope.photos = [];

var keyword = $scope.searchKeyword;
photoSearchService.findPhotos(keyword, function(photos) {
$scope.photos = photos;
});
};

Cuando es llamado, este método limpia temporalmente el modelo “photos” y solicita “photoSearchService” para encontrar fotos que coincidan con los criterios de búsqueda del usuario. Cuando la búsqueda se completa, el modelo de fotos es actualizado con los resultados. Presta atención al uso de “$scope.searchKeyword”. No se define explícitamente el modelo dentro de MainController. En cambio, existe porque lo declaraste usando ‘ng-model=”searchKeyword”‘ en el campo de texto de manera previa.

4.- Con la nueva acción “submitSearch()” de la aplicación en su lugar, solo necesitas dispararla desde la interacción del usuario con la vista. En index.html añade ‘ng-submit=”submitSearch()”‘ al elemento form:

<form class="search-field" ng-submit="submitSearch()">
<input type="text" ng-model="searchKeyword">
<input type="submit" value="Find">
<span class="search-message">photos of {{searchKeyword}}</span>
</form>

Ahora cuando un usuario envíe la solicitud, ejecutará la lógica definida en el controlador.

Con esto tu aplicación está completa.

Puedes ver la aplicación final aquí) Prueba buscar “water” o “mountains”.

Observaciones

Ahora que la aplicación está completa, toma un momento para analizar y hacer unas pocas observaciones.

Una característica notable de la aplicación es el poco código de javascript que necesita ser escrito. Ignorando los datos estáticos de la implementación del código de photoSearchService, así como las líneas que contienen solamente llaves de cierre, son menos de 20 líneas de javascript. Lo cual es impresionante.

También es importante notar algo que está ausente. Javascript es completamente libre del código que manipula el DOM. Esta característica de AngularJS lo hace muy diferente de otros frameworks de javascript. Esta característica hace mucho más fácil construir aplicaciones diseñadas con una clara separación entre la lógica de la aplicación y la vista que se muestra al usuario.

Finalmente, como la lógica es la que define cómo se lleva a cabo la búsqueda es encapsulada en un objeto de servicio, así es fácil cambiar la implementación rudimentaria del servicio por otra más robusta en el futuro, tal vez en un servicio que haga búsquedas en Flickr o Instagram. Mientras que el servicio sea implementado de una forma como la función “findPhotos(keyword, callback)” funcionará sin requerir ningún cambio al controlador, modelo o vista.

A dónde partir de acá

La aplicación que acabas de construir a lo largo de este artículo ha demostrados los fundamentos de AngularJS, pero esto es solo la superficie de muchas características que el framework ofrece. Para observar algunas de estas características, puedes visitar la Guía de Desarrollo de AngularJS o realizar el tutorial oficial de AngularJS.

AngularJS es un framework relativamente nuevo, así que las buenas prácticas de este aún son emergentes. Encontré este codigo fuente de referencia de aplicación en GitHub que puede servir como guía para prácticas útiles. Tambien puedes visitar el amistoso y activo Grupo de Google de AngularJS para buscar respuestas y hacer preguntas.

En mi experiencia, AngularJS es un framework para aplicaciones muy fácil para trabajar. La llegada de frameworks maduros para aplicaciones como AngularJS es un parteaguas por el cual los desarrolladores web deberían estar muy emocionados.

Si quiere aprender más en Activ ya tenemos nuestro curso de Angular para que te vuelvas todo un experto.

Este artículo está publicado en Adobe Developer Connnection (devnet) bajo licencia Creative Commons, escrito originalmente por Kris Schultz, Director del laboratorio de innovación de Resource.