angular (3): rutas

En esta entrada veremos cómo funciona el sistema de rutas en angular.

Lilanga

archivado en: JavaScript / 6 mayo, 2014 / taller:

En las entradas anteriores de esta serie dedicada a angular hemos estado viendo código sin preocuparnos mucho por la teoría, que es más aburrida, pero ahora conviene que hagamos un alto para repasar unos pocos conceptos. Luego seguimos con código.

Ya sabemos que angular sigue un patrón MV* (Modelo - Vista - Lo que sea), es decir, que separa la gestión de los datos en bruto, el modelo, de la parte encargada de la interacción con el usuario, la vista. Por analogía con un restaurante: la cocina sería el modelo, donde se preparan los platos y están todos los ingredientes; y la sala, donde comen los clientes, sería la vista. En un patrón clásico MVC, además, está el controlador, que serían los camareros, la parte del código encargada de enlazar la vista con el modelo. Sin embargo, en angular estas funciones del controlador están repartidas entre la vista y el modelo. Es un restaurante autoservicio :P.

Las vistas en angular consisten en un sistema de plantillas, templates, en las que se combinan tags de HTML con directivas, directives, esto es, con atributos propios que siempre empiezan por ng-, que son interpretados por angular para generar código HTML. Además, en estas plantillas, se pueden incluir partes que recogen dinámicamente datos del modelo y una forma de definirlas es poniéndolas entre dos pares de llaves {{}}.

Para asociar una parte de la vista con algún modelo, se utiliza la directiva ng-controller . El fragmento del DOM encapsulado en un tag con esta directiva forma un controller, que se comunica con su modelo correspondiente mediante un objeto denominado $scope, que se puede traducir como ámbito, alcance y objetivo. Por ejemplo, en la vista, en el archivo index.html, podemos tener un controller como este:

...

<body ng-app='miAplicacion'>

<div ng-controller='miControlador'>

{{ cadenaTexto }}

</div>

...

Y en el archivo main.js, su modelo-controller correspondiente.

var miControlador = function ($scope) {

$scope.cadenaTexto = 'hola Mundo';

};

Espero que todo esté claro hasta aquí, ahora vamos a hablar de módulos o, como se dice en inglés,  modules. En angular, cada parte de la aplicación debe ir agrupada en módulos. En la vista, el módulo está definido por la directiva ng-app, que en el ejemplo anterior denominé «miAplicacion», y en el modelo se hace mediante esta sentencia:

var nombre del módulo = angular.module('nombre del módulo de la vista', []);

Así, por ejemplo, en nuestro ejemplo, bastaría con añadir esta línea para definir el módulo:

var miModulo = angular.module('miAplicacion', []);

var miControlador = function ($scope) {

$scope.cadenaTexto = 'hola Mundo';

};

Ya veremos qué significa ese array [] en el segundo parámetro del módulo y su utilidad para definir dependencias, pero ahora me interesa que comprendamos cómo asociar los controladores del modelo a un módulo y esto se consigue variando la sintaxis anterior. En vez de soltar a cascoporro la función o el objeto, lo enviamos como parámetro del método controller del objeto en el que hemos definido el módulo. Algo así:

var miModulo = angular.module('miAplicacion', []);

miModulo.controller("miControlador", function ($scope){

$scope.cadenaTexto = 'hola Mundo';

});

Esto quedará más comprensible con un ejemplo, pero antes vamos a ver qué son las rutas.

Rutas

La gracia de angular es que permite crear single page aplications (SPA), aplicaciones de una sola página, de forma sencilla y ordenada. Para eso, es decir, para que todo suceda en la misma página sin salto alguno, tenemos a nuestra disposición un servicio de rutas ($routes). Este servicio, es decir, este conjunto de procesos, se combina con la directiva ng-view, que sirve para renderizar fragmentos de una vista. Veamos un ejemplo, que es como más claro queda.

Vamos a crear una página muy sencilla sobre mitología. En la portada habrá un listado con tres zonas culturales (Grecia, Escandinavia y Mesoamérica). Al pulsar sobre una de ellas, en la parte inferior se mostrarán algunos dioses característicos de esa zona.

1). Angular no tiene incorporado el módulo que gestiona las rutas, así que lo primero que debemos hacer es bajar el archivo angular-route.min.js e incorporarlo a la aplicación en index.html, después de que hayamos cargado angular, claro está. Siguiendo el código de anteriores entradas, lo podemos guardar en vendor.

<!DOCTYPE html>

<head>

<meta charset="utf-8">

<title></title>

</head>

<body'>

<!-- Aquí irá la plantilla inicial -->

<script src="js/vendor/angular.min.js"></script>

<script src="js/vendor/angular-route.min.js"></script>

</body>

</html>

2). Ahora vamos a cambiar la estructura de directorios que estábamos manejando. En vez de soltarlo todo a cascoporro en main.js, separamos la definición del módulo de los controladores y creamos un directorio denominado templates, en el cual guardaremos las plantillas que necesitaremos. El módulo del modelo lo guardaremos en app.js y los controladores en otro archivo denominado controllers.js. Además, crearemos un archivo por cada plantilla (escandinavia.html, grecia.html, mesoamerica.html y main.html). Al final, nos debería quedar algo así:

/index.html

/js/app.js

/js/controllers.js

/templates/main.html

/templates/escandinavia.html

/templates/grecia.html

/templates/mesoamerica.html

3). En index.html preparamos el menú, que consiste en un listado donde los enlaces son como las anclas de toda la vida, es decir, precedidos por almohadillas. Fijaos en la directiva ngView. Ahí es donde se irán mostrando las plantillas que iremos cargando dinámicamente. Además, inicializamos la aplicación con la directiva ng-app, que llamaremos appMitologia (o lo que nos apetezca).

<body ng-app='appMitologia'>

<h3>Dioses</h3>

<ul>

<li><a href='#grecia'>Grecia</a></li>

<li><a href='#escandinavia'>Escandinavia</a></li>

<li><a href='#mesoamerica'>Mesoamérica</a></li>

</ul>

<div ng-view></div>

<script src="js/vendor/angular.min.js"></script>

<script src="js/vendor/angular-route.min.js"></script>

<script src="js/app.js"></script>

<script src="js/controllers.js"></script>

</body>

4). En controllers.js ponemos los controladores, uno por cada plantilla. Van precedidos por moduloMitologia, que es como llamaremos al módulo del modelo.

moduloMitologia.controller("controllerMain", function ($scope){

$scope.saludoInicial = 'Selecciona una mitología';

});

moduloMitologia.controller("controllerGrecia", function ($scope){

$scope.dioses = [ {nombre: 'Zeus'}, {nombre: 'Afrodita'}, {nombre: 'Atenea'} ];

});

moduloMitologia.controller("controllerEscandinavia", function ($scope){

$scope.dioses = [ {nombre: 'Odin'}, {nombre: 'Thor'}, {nombre: 'Loki'} ];

});

moduloMitologia.controller("controllerMesoamerica", function ($scope){

$scope.dioses = [ {nombre: 'Quetzalcoatl'}, {nombre: 'Tezcatlipoca'}, {nombre: 'Tlaloc'} ];

});

5). Repetimos el mismo código para las plantillas de dioses y en la principal mostramos el texto inicial.

Para mesoamerica.html, grecia.html y escandinavia.html, algo así:

<ul>

<li ng-repeat='dios in dioses'>{{dios.nombre}}</li>

</ul>

y en main.html, esto otro:

<p> {{ saludoInicial }}</p>

6). Y ahora ya con todo listo, vamos al archivo app.js, donde desarrollaremos el sistema de rutas. Primero declaramos el módulo, en el cual indicamos que tiene como dependencia el módulo de ngRoute. Al igual que sucede con el Require o cualquier otro sistema similar, lo que conseguimos así es decirle a javaScript: no ejecutes esto que sigue hasta que no se haya cargado lo que te indico en el array que te paso como segundo parámetro.

var moduloMitologia = angular.module('appMitologia', ['ngRoute']);

Y luego ya podemos usar $routeProvider para indicar qué plantilla (templateUrl), con qué controlador (controller) debe cargarse cada vez que en la url (when) hay determinado path. Además, en otherwise, especificamos una ruta por defecto.

var moduloMitologia = angular.module('appMitologia', ['ngRoute']);

moduloMitologia.config(function($routeProvider) {

$routeProvider

.when("/", {

templateUrl : "templates/main.html",

controller : "controllerMain"

})

.when("/grecia", {

templateUrl : "templates/grecia.html",

controller : "controllerGrecia"

})

.when("/escandinavia", {

templateUrl : "templates/escandinavia.html",

controller : "controllerEscandinavia"

})

.when("/mesoamerica", {

templateUrl : "templates/mesoamerica.html",

controller : "controllerMesoamerica"

})

.otherwise({ reditrectTo : "/" });

});

Ale op! pues ya está... al pulsar ahora sobre algún elemento de la lista del menú, en ngView se carga la vista correspondiente.

Importante: para ver este ejercicio hay que abrirlo con firefox o desde xamp o desde un servidor o desde node o alguna vaina similar, pues de lo contrario nos aparecerá el cross-domain de chrome.

Seguimos en la próxima entrada, que esta ya es un tocho infumable.

|| Tags:

valoración de los lectores sobre angular (3): rutas

  • estrellica valoración positiva
  • estrellica valoración positiva
  • estrellica valoración positiva
  • estrellica valoración positiva
  • estrellica valoración negativa
  • 4.4 sobre 5 (11 votos)

¿Te ha parecido útil o interesante esta entrada?
dormido, valoración 1 nadapensativo, valoración 2 un poco sonrisa, valoración 3 a medias guiño, valoración 4 bastante aplauso, valoración 5 mucho

Tú opinión es muy importante, gracias por compartirla!

Una respuesta a “angular (3): rutas

  1. hola, tengo un problema. cuando quiero redirecctionar la página nunca me funciona. veo los ejemplos y todo correcto, pero copio o descargo el código a mi pc, se me carga bien la página principal pero no al clicar en los links. alguna ayuda por favor??? gracias