Diseño de las aplicaciones single-page

Conceptos básicos

El siguiente ejemplo ilustra claramente la idea de un aplicación de una sola página SPA (Single Page Application). Ejecútela desde plunker a través del enlace :

Version 1: ejemplo tomado y adaptado de WebSystique (El sitio WebSystique).

Version 2: versión 2 ejemplo Bussiness

Cuando el usuario navega por la aplicación, hay zonas de la pantalla que se van actualizando para reflejar el nuevo estado. En la figura anterior, los estados de la aplicación se muestran en el árbol de la derecha, así como la forma para el usuario de alcanzarlos. Por ejemplo, para llegar al estado Show Products se debe primero llegar al estado Business.

Esta noción de estados nos va a ayudar a diseñar aplicaciones más modulares: cada módulo tiene define un conjunto de estados en los que ofrece al usuario servicios relacionados con el módulo. Del ejemplo, podemos pensar en un módulo Business que ofrece tres estados: Business, Show Products y Show Services. El otro módulo es Portfolio, que en el ejemplo tiene un único estado.

Para cada módulo se puede entonces diseñar sus estados. Cada estado, debe tener definido, cuál es la información que despliega (las vistas o templates), cuál es el controlador o controladores que las manejan y cuáles son los servicios de la aplicación que van a utilizar.

Adicionalmente, cuando los proyectos empiezan a crecer y hay varios desarrolladores trabajando al mismo tiempo sobre ellos, es importante definir unas convenciones de organización de los archivos para reflejar los módulos y facilitar la localización de cada una de las partes.

Fíjese que esta buena práctica es independiente de la tecnología que se esté utilizando para desarrollar el proyecto.

Nuestra convención es la siguiente. Hay una carpeta modules y dentro de esta una carpeta por cada uno de los módulos de la aplicación que contendrá los archivos relacionados con él:

SPA en Angular

EL framework ui-router de Angular fue diseñado para facilitar el desarrollo de aplicaciones de una sola página. Este framework utiliza el concepto de estado al que se le puede asociar, entre otras cosas, vistas, controladores y rutas para acceder a los servicios REST de la aplicación. Define además un mecanismo fácil para definir la navegación entre los estados.

Módulos

Siempre hay un módulo principal de la aplicación que define las dependencias con los otros módulos. La figura siguiente muestra que en el ejemplo, el módulo llamado routingDemoApp es el principal y depende del módulo externo ui-router y de los módulos de la aplicación: BusinessModule y PortfolioModule.

El código que refleja la figura anterior se encuentra en el archivo app.js:

var App = angular.module('routingDemoApp', ['ui.router', 'BusinessModule', 'PortfolioModule']);

Cada uno de los módulos de la aplicación se define en su propio archivo dentro del folder correspondiente. Por ejemplo, en el archivo src/modules/bussiness/business.mod.js tenemos la definción de BusinessModule que solo depende de ui-router:

var mod = angular.module('BusinessModule', ['ui.router']); // aquí va el resto del código del módulo

Las Vistas

Primero vamos a revisar cómo se definen las vistas o templates y luego vamos a explicar como definimos los estados y los asociamos con las vistas. El layout principal de la aplicación del ejemplo, se muestra en la siguiente figura. La información del estado business y sus hijos Show products y Show Services se desplegará en la zona que esta indicada como Vista Principal:

Este layout está definido en el archivo index.html. Note el tag ui-view. Allí se está definiendo la vista principal, en este caso no tiene nombre:

<body class="container"> <h3>AngularJS UI Router Application</h3> <nav class="navbar navbar-default row"> <div class="container-fluid"> <div class="navbar-header"> <ul class="nav navbar-nav"> <li><a ui-sref="business">Business</a></li> <li><a ui-sref="portfolio">Portfolio</a></li> </ul> </div> </div> </nav> <div class="row"> <div class="span12"> <div class="well" ui-view></div> </div> </div> </body>

La línea:

<li><a ui-sref="business">Business</a></li>

Significa que cuando el usuario haga click en el link Business, la aplicación pasará al estado business.

La línea:

<li><a ui-sref="portfolio">Portfolio</a></li>

Significa que cuando el usuario haga click en el link Portfolio, la aplicación pasará al estado portfolio.

En el caso del estado portfolio el layout que se utiliza en la aplicación es el siguiente:

En este caso, la vista de portfolio define dos nuevas vistas dentro de la principal. Esto se ve en el archivo que contiene la definición dela vista de portafolio: src/modules/portafolio/portafolio.html

<h4>Portfolio Page</h4> <hr/> <strong>This page shows multiple named views in action.</strong> <div class="row"> <div class="col-sm-6"> <div class="panel panel-default" ui-view="view1"></div> </div> <div class="col-sm-6"> <div class="panel panel-default" ui-view="view2"></div> </div> </div>

Las nuevas vistas se definen en las líneas:

<div class="panel panel-default" ui-view="view1"></div> y <div class="panel panel-default" ui-view="view2"></div>

utilizando la directiva ui-view note que estas vistas tienen un nombre que se haá usado desde el estado para decidir dónde desplegar la información.

Los Estados

Un estado representa un punto de interacción de la aplicación con el usuario final. Un estado contiene, entre otras propiedades, la información de cómo lucirá la interfaz y de cuáles servicios se realizará.

UI-Router de Angular ofrece varios servicios para tar la creación y manipulación de los estados:

$stateProvider

Los esados de un módulo deben registrarse en el servicio $stateProvider utilizando el método state. La información básica para definir un estado es el nombre y un objeto que contiene en sus propiedades la configuración del estado:

$stateProvider.state(name, {})

Las propiedades principales de la configuración del estado son:

Propiedad Tipo Descripción
Template string Código html
TemplateUrl string archivo (path completo) que contiene el código Html
controller string o function Si es un string corresponde al nombre de un controlador que ya fue registrado.
controllerAs String permite redefinir de manera estándar el nombre del controlador. Los templates hacen referencia a este nombre.
url string Corresponde a la ruta del estado
views map Permite que un estado utilice varias vistas. Si esto no existe, la vista por defecto es la que no tiene nombre

Puede encontrar más infmación y ejemplos sobre estas propiedades en: API UI-Router $StateProvider.

Vamos a ver algunos de estos elementos en el ejemplo y otros en ejemplos posteriores. Este ejemplo corresponde ala definición de los tres estados del módulo BusinessModule. Aquí a la configuración general del módulo se esta definiendo el valor de sus estados ($StateProvider y definiendo la ruta por defecto en caso de que se, por alguna razón involuntaria, la aplicación navegará hacia un estado que no existe ($urlRouterProvider.otherwise).

Estados del módulo BusinessModule

Veamos la definición de los estados uno por uno:

  1. 'business': etse estado configura la url y el templateURl que e sle archivo que contiene lso links ahacia los otros estador. Aquí no hay u controlador proque no se necesita.
  2. 'business.products': define la url, el template para los productos que contiene el título y la lista de productos que están en el scope. Define un controllador que contiene directamente la función. Esta función inicializa la lista de productos en el scope para que sea utilizada por el template.
  3. 'business.services': similar al estado anterior.
var mod = angular.module('BusinessModule', ['ui.router']); mod.config(['$stateProvider', '$urlRouterProvider', function ($stateProvider, $urlRouterProvider) { var basePath = 'src/modules/business/'; $urlRouterProvider.otherwise("/business"); $stateProvider .state('business', { url: "/business", templateUrl: basePath+"business.html" }) .state('business.products', { url: "/products", templateUrl: basePath+"products.html", controller: function ($scope) { $scope.products = ["Computer", "Printers", "Phones", "Bags"]; } }) .state('business.services', { url: "/services", templateUrl: basePath+"services.html", controller: function ($scope) { $scope.services = ["Selling", "Support", "Delivery", "Reparation"]; } }); }]);
Estados del módulo PortfolioModule

Este módulo tiene un único estado pero utiliza tres vistas distintas.

$stateProvider.state('portfolio', { url: "/portfolio", views: { "": {templateUrl: basePath+"portfolio.html"}, "view1@portfolio": {template: "Write whatever you want, it's your virtual company."}, "view2@portfolio": {templateUrl: basePath+"clients.html", controller: function ($scope) { $scope.clients = ["HP", "IBM", "MicroSoft"]; } } } });

La vista principal (en este ejemplo no tiene nombre) tiene asociado el template de portafolio. Este template tiene definido los lugares que coresponderán a las vistas view1 y view2.

<h4>Portfolio Page</h4> <hr/> <strong>This page shows multiple named views in action.</strong> <div class="row"> <div class="col-sm-6"> <div class="panel panel-default" ui-view="view1"></div> </div> <div class="col-sm-6"> <div class="panel panel-default" ui-view="view2"></div> </div> </div>

En el caso del módulo BusinessModule tenemos que el estado business.services es un estado embebido (nested state) (services en business). El estado business es el padre del estado services haciendo que este pueda heredar las propiedades de su padre.

En el caso del módulo PortfolioModule tenemos la vista view1 y la vista view2 embebidas dentro de la principal de portafolio (nested views).


Referencias y Material complementario

results matching ""

    No results matching ""