Aplicaciones en Angular

Una aplicación Angular es un conjunto de módulos donde cada módulo debe ocuparse de un conjunto cohesivo de elementos para manipular un concepto lógico del dominio del problema. Un módulo en Angular contiene un conjunto de directivas, servicios, fábricas, constantes, controladores y otros elementos.

Los elementos básicos que una aplicación Angular debe tener son:

  • Los módulos: sirven para contener partes funcionalmente cohesivas de una aplicación. Por ejemplo, en una aplicación de venta de libros podemos decidir que en un módulo tenemos la funcionalidad racionada con los libros, en otro la relacionada con los autores, otro con los clientes, otro con las ventas, etc.
  • Los templates: Los templates o vistas con los elementos html (extendidos con las directivas angular) que van a permitir que un usuario visualice e interactue con la aplicación. Para cada módulo se diseñarán sus correspondientes vistas. Las vistas despliegan información de la aplicación y tienen asociadas en sus elementos de interacción, por ejemplo en los botones, acciones o funciones que la aplicación debe ejecutar para lograr los objetivos de la aplicación.
  • Los controladores: Los controladores se asocian con las vistas y contienen las acciones que se van a invocar desde ellas.

En la siguiente figura, un usuario interactura con una vista de una aplicación y al interactuar con los elementos de la interface, se invocan acciones que están definidas en el controlador:

Los módulos

Un módulo angular define una aplicación. Un módulo es el contenedor de elementos de la aplicación como los controladores, los filtros, etc.

Tomando el ejemplo básico "Hello World" de la documentación oficial de Angular

Un módulo se define utilizando la función angular.module('nombredelmodulo', [])

En el segundo parámetro de tipo arreglo, que en el ejemplo está vacío [], se incluyen las dependencias del módulo, es decir referencias a otros módulos que se van a utilizar aquí. Si el módulo no tiene dependencias igual se debe definir el parámetro pero vacío. Si se omite este parámetro, Angular lo interpretará como una invocación al módulo y no como una declaración de un módulo. En el siguiente ejemplo se está definiendo un módulo llamado holaMundoEjemplo en la línea 1. Este módulo no tiene dependencias por eso los []. La variable app contendrá la definición del módulo.

En la línea 2, se está agregando al módulo un controller. Cada controlador tiene un nombre, en el ejemplo es 'holaMundoControlador' y el código de una función, en el ejemplo es la holaMundoControlador que se esta invocando sin los (). En este caso el código está definido en la línea 4.

var app = angular.module('holaMundoEjemplo', []); app.controller('holaMundoControlador', holaMundoControlador); function holaMundoControlador() {}

Otra manera de escribir la creación del controlador es incluir directamente la definición de la función en el argumento del controlador:

var app = angular.module('holaMundoEjemplo', []); app.controller('holaMundoControlador', function () {});

Una aplicación puede tener muchos módulos. Lo que convierte un módulo en la aplicación principal es la referencia que se hace a él en él desde las vistas de la utilizando la directiva ng-app. En el siguiente código vemos esto. En la línea 11 , asociado con el tag body está la directivang-app cuyo valor es el nombre del módulo que definimos que se convertirá en el módulo principal.

Los controladores se asocian con elementos del template. En el ejemplo, en la línea 12, utilizando la directiva ng-controller estamos asociando con ese elemento div (y todo lo que él contiene) el controlador que definimos llamado holaMundoControlador.

<!doctype html> <html> <head> <meta charset="UTF-8"> <title>Ejemplo Hola Mundo</title> <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular.min.js"></script> <script src="script.js"></script> </head> <body ng-app="holaMundoEjemplo"> <div ng-controller="holaMundoControlador"> Nombre: <input type="text" ng-model="nombre"> <hr> {{saludo}} </div> </body> </html>

Note que en la línea 15, la expresión saludo no está definida en la vista entonces debe ser algo que esté definido en el controlador holaMundoControlador:

app.controller('holaMundoControlador', function($scope) { $scope.nombre = "Juan"; $scope.saludo = "Hola " + $scope.nombre; });

EL siguiente diagrama muestra parte de los objetos javascript que crea Angular, para el ejemplo anterior, y las relaciones entre ellos.

Data binding

Las variables definidas utilizando ng-model en el template, se transforman en nodos DOM. Además, quedan creadas en una zona lógica de Angular llamada el scope. La variable $scope es una variable predefinida de angular. Los valores de las variables que se guarden allí siempre estarán sincronizados entre la vista y el controlador; evitando que el desarrollador tenga que actualizar explícitamente las vistas de la interface. En el ejemplo anterior podemos ver este comportamiento en los siguientes casos:

  1. la variable nombre se inicializa en el controlador y este valor automáticamente se despliega en la vista dentro del campo de texto como valor inicial.
  2. la variable nombre cambia cuando el usuario ingresa un valor en el campo de texto. En el controlador se refleja el nuevo valor en $scope.nombre.
  3. la variable saludo obtiene valor solo en el controlador pero como se utiliza en la vista en la expresión {{saludo}} la vista se actualiza cada vez que en el controlador se cambia su valor.

Angular se ocupa de establecer un enlace entre las variables del template y el scope, de tal forma que cuando se actualicen sus valores en un lado, se actualizará automáticamente en el otro.

Ejemplo Shopping cart (básico) en angular

Descripción

Vamos a desarrollar el ejemplo del Shopping Cart en angular. Los requerimientos:

  1. Se debe poder crear ítems de compra con descripción, cantidad y costo
  2. Se debe incluir el subtotal de cada ítem.
  3. Se debe totalizar toda la lista del Shopping Cart
  4. Se debe poder borrar un ítem de compra.

Diseño

Primero definimos un prototipo de cómo debería verse la aplicación:

Segundo diseñamos la estructura de datos. Podemos utilizar una clase UML para representar las propiedades de la estructura y los métodos que se necesitan:

La estructura tiene un arreglo de ítems donde cada uno tiene su descripción, cantidad y costo. Los métodos corresponden con los requerimientos definidos antes

Implementación

Debemos implementar la vista o template de la aplicación y el controlador asociado con esta vista y que contendrá la estructura y las funciones.

Template

La estructura es la que se presenta en el siguiente fragmento. Note la directiva ng-app y ng-controller. Lo segundo que hay que notar es la inclusión de la librería angular (líneas 5). Hay que entender dos cosas:

  1. se debe incluir porque se utiliza en el proyecto. En este caso, la librería está en un directorio local del proyecto que se llama bower_components.
  2. la información de qué versión de angular estamos utilizando y de cómo la descargamos la podemos revisar en el enlace: Administrar librerías javascript.
<!DOCTYPE html> <html> <head> <script src="bower_components/angular/angular.js"></script> <script src="src/app.js"></script> </head> <body ng-app='MainApp'> <h2>Shopping Cart Example</h2> <div ng-controller='shopController'> // Aquí va la tabla </div> </body> </html>

En este ejemplo utilizamos una tabla para presentar los elementos del shopping cart. La relación entre el template y el controlador está en los tags:

  1. ng-model para indicar variables de la estructura.
  2. ng-click para invocar los métodos del controlador.

Adicionalmente, estamos utilizando la directiva angular ng-repeat que facilita la iteración sobre la lista de los ítems y los filtros {% raw %}{{expresión | filtro}}{% endraw %} que facilita cambiar elementos en el DOM.

{% raw %} <table class="table"> <tr> <th>Description</th> <th>Qty</th> <th>Cost</th> <th>Total</th> <th></th> </tr> <tr ng-repeat="item in invoice.items"> <td> <input type="text" ng-model="item.description" class="input-small"> </td> <td> <input type="number" ng-model="item.qty" ng-required class="input-mini"> </td> <td> <input type="number" ng-model="item.cost" ng-required class="input-mini"> </td> <td>{{item.qty * item.cost| currency}}</td> <td>[<a href ng-click="removeItem($index)">delete</a>]</td> </tr> <tr> <td><a href ng-click="addItem()" class="btn btn-small">add item</a> </td> <td></td> <td>Total:</td> <td>{{total()| currency}}</td> </tr> </table> {% endraw %}

El Controlador

El controlador es una función constructora de objetos que representa la estructura del invoice y sus métodos. Note que tanto la estructura como los métodos quedan en la variable $scope de angular.

var app = angular.module('MainApp', []); app.controller('shopController', function($scope) { $scope.invoice = { items: [{ qty: 10, description: 'item', cost: 9.95 }] }, $scope.addItem = function() { $scope.invoice.items.push({ qty: 1, description: '', cost: 0 }); }, $scope.deleteItem = function(index) { $scope.invoice.items.splice(index, 1); }, $scope.subTotal = function(item) { return item.qty * item.cost; }, $scope.total = function() { var total = 0; angular.forEach($scope.invoice.items, function(item) { total += item.qty * item.cost; }); return total; } });

Ver el ejemplo Completo en Plunker Descargar el ejemplo de Github
Plunker Github

results matching ""

    No results matching ""