Tabla de Contenidos

7.2 $routeProvider

Para usar las rutas en AngularJS lo primero que necesitaremos será configurarlo para poder asociar a la ruta 1) la página HTML que se debe cargar al navegar a esa ruta. Para ello tenemos el servicio $routeProvider de AngularJS.

Este servicio tiene 2 métodos:

when

El método when de $routeProvider permite asociar una ruta a una página HTML aunque como mínimo también se indica el controlador que se usará en esa página.

El método when acepta dos parámetros:

Veamos un ejemplo:

  var path='/pagina1';

  var route={
    templateUrl: "pagina1.html",
    controller: "Pagina1Controller"
  }

  $routeProvider.when(path,route);

En este ejemplo, si el usuario añade a la página principal ”#/pagina1” se cargará dentro de la página principal la página HTML llamada pagina1.html y como controlador de esa nueva página se usará Pagina1Controller.

Se podría poner dentro de la nueva página la directiva ng-controller y especificar dentro de la propia página el controlador en vez de al definir la ruta, sin embargo nunca lo he visto en ningún ejemplo de AngularJS, por lo tanto no recomiendo hacerlo.

Recordad que aunque el path sea /pagina1 y la página se llame pagina1.html realmente no tienen por qué coincidir en nada los nombres, aunque por coherencia suelen ser parecidos.

No tendría mucho sentido navegar a la ruta /ventas y que se cargara la página compras.html aunque no hay nada que lo impida.

El código anterior habitualmente suele compactarse de la siguiente forma y es como lo usaremos a partir de ahora:

  $routeProvider.when('/pagina1', {
    templateUrl: "pagina1.html",
    controller: "Pagina1Controller"
  });

otherwise

En caso de que el usuario pusiera una ruta que no existe o simplemente no pusiera ninguna ruta , la página principal se podría quedar en blanco ya que no cargaría ninguna página. Para evitar éso AngularJS permite, en caso de que no pongamos ninguna ruta o que la ruta no exista, que se navegue a una ruta predeterminada. Para ello usamos el método otherwise.

El método otherwise acepta un único parámetro con un objeto, teniendo el objeto la propiedad redirectTo con el path de la ruta a la que se navegará.

Veamos un ejemplo:

  $routeProvider.otherwise({
        redirectTo: '/pagina1'
  }); 

Lo que hacemos es decirle a AngularJS que en caso de que no pongamos ruta o la ruta sea desconocida es como si fuera la ruta /pagina1.

ng-view

Ya hemos visto cómo definir las rutas pero nos falta una cosa por especificar , ¿en qué parte de la página principal se carga la página HTML de cada ruta? Podríamos pensar que la página cargada ocupará toda la página principal,pero, aunque podría hacerse, no es lo normal.

Si miramos las capturas de pantalla de gmail, la parte izquierda y la superior no cambian en cada ruta por lo que todo ese HTML debería estar en la página principal. Por lo tanto, cada página de la ruta solo se debería cargar en un tag, por ejemplo<div>, que habilitáramos para ello. La forma de decirle a Angular dónde tiene que cargar la página HTML de la ruta es simplemente añadiendo la directiva ng-view al elemento donde quedamos que se cargue.

Veamos un ejemplo:

<!DOCTYPE html>
<html ng-app="app">

<head>
  <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.19/angular.min.js"></script>
  <script src='//ajax.googleapis.com/ajax/libs/angularjs/1.2.19/angular-route.min.js'></script>
  <script src="//code.angularjs.org/1.2.19/i18n/angular-locale_es-es.js"></script>
  <script src="script.js"></script>
</head>

<body>
  <h1>éste es el titulo y no cambia</h1>

  <div ng-view></div>

  <h3>ésto es un pie y no cambia</h3>

</body>

</html>

Ya tenemos todo preparado pero ahora falta saber cómo se navega a la ruta. Hay dos formas:

La solución es muy fácil, realmente cada ruta es un fragmento de la URL actual, así que sólo tenemos que navegar al fragmento correspondiente a la ruta.

Si tenemos definida la ruta:

/pagina1

Podemos poner un link de la siguiente forma:

<a href="#/pagina1">Ir a la pagina 1</a>

Recuerda poner la almohadilla ”#” antes de las rutas en los links.

Servicio $location desde JavaScript

Desde JavaScript AngularJS tiene un servicio que permite navegar a las rutas. Este servicio se llama $location.

No vamos a describir todas las funcionalidades de $location. Únicamente decir que tiene un método llamado path al que le pasamos la ruta y hace que se navegue hasta esa ruta.

Si tenemos definida la ruta:

/pagina1

por ejemplo, en un controlador podemos hacer lo siguiente:

app.controller("Pagina1Controller", ["$scope","$location",function($scope,$location) {
  
   $scope.irPagina1 = function () {
      $location.path("/pagina1");
   };  
   
}]);

Ahora desde cualquier parte de la página ya podemos llamar al método y navegar a esa ruta.

Recuerda que al usar el servicio de $location no hay que poner la almohadilla ”#”

Módulo ng-route

Una cosa a tener en cuenta al usar las rutas es que todo lo relacionado con ellas está en un módulo separado del núcleo de AngularJS llamado ngRoute y en un fichero llamado angular-route.js, por lo tanto deberemos:

En la página principal del fichero HTML deberemos cargar el fichero JavaScript mediante:

  <script src='//ajax.googleapis.com/ajax/libs/angularjs/1.2.19/angular-route.js'></script>

Y al crear el módulo de nuestra aplicación deberemos hacer que dependa de él:

var app = angular.module("app", ['ngRoute']);

Para usar las rutas , recuerda cargar el fichero angular-route.js y hacer que tu aplicación dependa del módulo ngRoute

  <script src='//ajax.googleapis.com/ajax/libs/angularjs/1.2.19/angular-route.js'></script>

var app = angular.module("app", ['ngRoute']);

Alternativa: ui-router

Acabamos de ver el funcionamiento básico de las rutas en AngularJS 1.2 y en los siguientes temas veremos más funcionalidades del módulo de rutas de AngularJS 1.2. Sin embargo, el módulo de rutas de AngularJS 1.2 tiene una funcionalidad muy básica. En aplicaciones reales no deberíamos usarlo y como substituto de facto está el proyecto UI Router. UI Router tiene muchas más funcionalidades y debe ser nuestra primera elección como servicio de rutas.

El equipo de AngularJs tiene pensado mejorar el servicio de rutas para AngularJS 2.0 pero la versión 2.0 aún queda muy lejos en el tiempo por lo que no es una opción todavía pero en el momento de escribir este curso Brad Green , un desarrollador de AngularJS,twitteó que piensan añadir a Angular 1.3 el sistema de rutas de Angular 2.0 por lo que dentro de poco tendremos un servicio de rutas adecuado en AngularJS y no será necesario UI Router.

Por todo ello he decidido no contar UI Router ya que dentro de poco no será tan necesario al tener ya un servicio de rutas adecuado en AngularJS 1.3. Así que me he centrado en contar el sistema actual que es bastante sencillo, a sabiendas de que cuando salga AngularJS 1.3 deberías aprender el nuevo servicio de rutas.

Si tienes que hacer ahora un proyecto real usa UI Router pero si puedes esperar a AngularJS 1.4 (el 5 de Marzo de 2015) mejor usa su servicio de rutas.

Actualización 20/10/2014.

Hace unos días se ha publicado la versión 1.3 de AngularJS y no tiene el nuevo sistema de rutas así que tendremos que esperar a AngularJS 2.0 para verlo. Por lo tanto recuerda en proyectos reales usar UI Router

Actualización 28/10/2014

Vuelve a haber nuevas noticias sobre éste tema.En las conferencias de ng-europe 2), hubo una charla el 24/10/2014 titulada The new Router for AngularJS, en ella se dijo que el nuevo sistema de rutas será portado a AngularJS 1.3.

Actualización 15/12/2014

Mas noticias sobre éste tema.En el blog de AngularJS se ha publicado el plan para Angular 1.4 e incluye el nuevo sistema de rutas!!!! La versión estará para el 5 de Marzo de 2015 coincidiendo con la ng-conf

Ejemplo

El ejemplo que vamos a hacer es una página principal llamada index.html y 3 páginas que se cargarán dentro de ella. También vamos a poner 3 enlaces para poder cambiar entre las distintas páginas.

<!DOCTYPE html>
<html ng-app="app">

<head>
  <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.19/angular.min.js"></script>
  <script src='//ajax.googleapis.com/ajax/libs/angularjs/1.2.19/angular-route.min.js'></script>
  <script src="//code.angularjs.org/1.2.19/i18n/angular-locale_es-es.js"></script>
  <script src="script.js"></script>
</head>

<body>
  <h1>Éste es el título y no cambia</h1>
  <ul>
    <li><a href="#pagina1">Ir a la pagina 1</a>
    </li>
    <li><a href="#pagina2">Ir a la pagina 2</a>
    </li>
    <li><a href="#pagina3">Ir a la pagina 3</a>
    </li>
  </ul>
  <div ng-view></div>

  <h3>Ésto es un pie y no cambia</h3>

</body>

</html>

Las 3 páginas que forman parte de las rutas se llaman: pagina1.html , pagina2.html y pagina3.html y su código es el siguiente:

<h1>Soy la pagina 1</h1> 
{{mensaje}}

<h1>Soy la pagina 2</h1> 
{{mensaje}}

<h1>Soy la pagina 3</h1> 
{{mensaje}}

Por último, el fichero con el JavaScript es el siguiente

var app = angular.module("app", ['ngRoute']);


app.config(['$routeProvider',function($routeProvider) {
  

  $routeProvider.when('/pagina1', {
    templateUrl: "pagina1.html",
    controller: "Pagina1Controller"
  });
  
  $routeProvider.when('/pagina2', {
    templateUrl: "pagina2.html",
    controller: "Pagina2Controller"
  });
  
  $routeProvider.when('/pagina3', {
    templateUrl: "pagina3.html",
    controller: "Pagina3Controller"
  });  
  
  $routeProvider.otherwise({
        redirectTo: '/pagina1'
  });   

}]);


app.controller("Pagina1Controller", ["$scope",function($scope) {
   $scope.mensaje="Texto cargado desde el controlador Pagina1Controller";
}]);

app.controller("Pagina2Controller", ["$scope",function($scope) {
   $scope.mensaje="Texto cargado desde el controlador Pagina2Controller";
}]);


app.controller("Pagina3Controller", ["$scope",function($scope) {
   $scope.mensaje="Texto cargado desde el controlador Pagina3Controller";
}]);

Como este ejemplo necesita ver cómo cambia la URL del navegador , es mejor abrir en una nueva página el ejemplo.

Referencias

1) que es realmente un fragmento de la URL
2) la conferencia europea sobre AngularJS