Angular.js para aplicaciones Windows Store: Primeras impresiones

Existe una gran variedad de frameworks javascript, Angular, Ember, knockout, etc. Todos ellos nos proporcionan algo que aquellos que hemos hecho wpf estábamos esperando: Data binding, y la posibilidad de usar patrones como MVVM.

En este artículo doy un vistazo a Angular.js, un framework desarrollado por Google que está dando mucho de que hablar, y, para hacerlo más interesante, he lo empleo dentro del contexto de una aplicación Windows 8, donde las reglas del juego cambian ligeramente.

Instalación y configuración

Para este proyecto, el primer paso es crear una aplicación vacía de Windows 8 con Javascript, podemos usar Visual Studio Express para ello.

Para incluir Angular.js, una cosa que podemos pensar es enlazar directamente a la CDN de angular desde nuestro fichero default.html:

<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.1/angular.min.js">
</script> 

Sin embargo nos encontramos con esto:

Usando la CDN de Angular JS

Es decir, no podemos usar una referencia no local para ficheros javascript con lo cual tendremos que descargarlo e incluirlo en nuestro proyecto manualmente. Podríamos además, estar tentados a instalarlo usando nuget, pero en mi opinión agrega demasiados archivos al proyecto.

Como anotación, recomiendo descargar la versión angular.js, no la angular.min.js, ya que tendremos que hacer algunos cambios más adelante.

Una vez tengamos el fichero agregado a nuestro proyecto, si intentamos compilar tendremos una segunda sorpresa:

Exccepcion con angular

Hay muchas maneras de resolver este error, pero el que a mí me ha funcionado pasa por editar la función problemática, y sustituir la llamada a la función insertBefore por:

MSApp.execUnsafeLocalFunction(function (){element.insertBefore(child, index);}); 

Con este ligero cambio, ya podremos ejecutar nuestra aplicación.

Las vistas

Para mostrar información por pantalla, en vez de construir el HTML manualmente y editar el DOM desde código javascript, simplemente usamos ciertas convenciones para incrustar datos dentro de una plantilla HTML.

<label>Name:</label>
<input type="text" ng-model="yourName" placeholder="Enter a name here" />
<h1>Hello {{yourName}}!</h1>

En este caso, el input genera una variable de nombre yourName, que se actualiza en el campo h1, en la región habilitada para ello. Estas variables encerradas entre llaves se pueden usar también dentro de los elementos html, por ejemplo para fijar la propiedad "src" de una imagen:.

 <img src="{{item}}" /> 

No tenemos que preocuparnos por la actualización, ya que al cambiar el contenido del dato, sea cual sea, el valor será actualizado automáticamente. Esto representa una diferencia bastante interesante respecto a otros frameworks como Knockout, donde para que se actualizara el objeto teníamos que definirlo con un tipo muy específico.

Controladores

El controlador se define como una clase javascript, con propiedades y funciones, las cuales luego suelen ser llamadas desde el código fuente, por ejemplo:

function TodoCtrl($scope) {
$scope.todos = [];

$scope.addTodo = function () {
$scope.todos.push({ text: $scope.todoText, done: false });
        $scope.todoText = '';
};

};

En este ejemplo se define un controlador, un campo llamado todos, y un método para almacenar en la lista el valor definido en la variable todoText. El $context es similar al this del standard, aunque con algunas variantes. La vista de este código se parece a algo así:

<h2>Todo</h2> {{todos.length}}
<form ng-submit="addTodo()">
    <input type="text" ng-model="todoText" placeholder="add new todo here" size="30" />
    <input class="btn-primary" type="submit" value="add" />
</form>

A diferencia de lo visto anteriormente, en este código definimos un controlador, accedemos al campo length del objeto todos definido anteriormente, y finalmente llamamos al método como resultado del envío de formularios.

Bucles (y bucles dentro de bucles)

Otra de las cosas interesantes que tiene, es el uso de los bucles para recorrer información:

<ul>
    <li ng-repeat="todo in todos">
        <p>{{todo.name}}</p>
        <span ng-repeat="item in todo.items">
            <img src="{{item}}" /></li>
    </li>
</ul>

En este caso representamos la estructura de todos, y asumiendo que todo es una estructura compuesta, Estos bucles además se pueden anidar, consiguiendo una mayor libertad a la hora de representar datos complejos.

Llamadas HTTP

Para poder hacer llamadas a un servidor externo mediante http solamente necesitamos la url y el método por el cual realizaremos la petición, para efectuar la llamada de la siguiente manera:

$http({ method: 'GET', url: 'http://url' }).
 success(function (data, status, headers, config) {

 }).
 error(function (data, status, headers, config) {

 });

Este código lo incluiremos en nuestro controlador sin llamadas adicionales, de tal manera que sea ejecutado al cargar el controlador. Si lo hacemos de esta manera nos encontraremos con un bonito error como el que se muestra a continuación:

Http error

Para evitar ese error, hemos de modificar la definición de nuestro controlador:

function TodoCtrl($scope)

De tal manera que ahora además de $scope, recibe $http:

function TodoCtrl($scope, $http)

Resumen

Esto es solamente una primera toma de contacto, y he de decir que la primera impresión ha sido muy buena. La documentación y la cantidad de ejemplos disponibles en internet ayudan también a que la curva de aprendizaje sea simple.

Enlaces adicionales