Angularjs

5.3. $routeProvider & $routeParams

$routeProvider

$routeProvider define las rutas mediante sus dos métodos como veíamos anteriormente:

when (path, route);

Cuando encuentra una url entonces aplica la ruta...

  • path es la url que se muestra en el navegador web. Al ser una ruta single-page tenemos que se muestra mediante hashtag # en plan www.miapp.com/#/pagina1.

  • route es el objeto ruta que tiene ciertas [propiedades] (https://docs.angularjs.org/api/ngRoute/provider/$routeProvider) entre las que destacamos:

    • templateUrl. Url de la plantilla / vista HTML que va a cargar. Devuelve el HTML que será cargado en ng-view o en directivas ng-includes. Existe también el parámetro template donde se pone el código HTML en el momento pero por escalabilidad es preferible utilizzar templateUrl,

    • controller. Nombre del controlador que va a ejecutar o incluso se puede definir la función del controlador al instante (no recomendable). De esta manera indica, para esta ruta carga la vista de templateURL con el controlador indicado.
      También existe el parámetro controllerAs (alias del controlador) que hace que el controlador sea publicado en el scope (ámbito) con ese nombre alias.

  • resolve. Es un mapa de dependencias opcional que se inyectan sobre el controlador. Si esas dependencias son promises el enrutador esperará a inyectarlas antes de instanciar el controlador. Si todo va bien se disparará el evento $routeChangeSuccess y si no el $routeChangeError. El objeto que resuelve es key nombre de la dependencia y factory nombre del servicio a ejecutar o la función directamente.
  • redirectTo. Permite redireccionar a otra ruta. path or function that returns a path to an html template that should be used by ngView.

  • [reloadOnSearch=true]. Recarga la ruta cuando hay cambios en la url, en $location. Valor por defecto a true, es decir, recargar la ruta.

  • [caseInsensitiveMatch=false]. Evalua si es keysensitive o no. Valor por defecto false, es decir, tiene en cuenta las mayúsculas y las minúsculas.

otherwise (params);

Las rutas se leen en cascada una debajo de la otra. Si ninguna ruta coincide entonces se ejecuta el método otherwise. otherwise( {redirectTo: '/'});De manera que si se pone cualquier url en la barra de navegación la app hará un redirect hacia la ruta raíz (en este caso).


Ejemplo routing

var uazonApp = angular.module("uazonApp",['ngRoute','libros'])
.config(
    function($routeProvider)
    {
        $routeProvider
        .when('/listado',
        {
            templateUrl:'src/views/listado.html',
            controller: 'LibrosCtrl'
        })
        .when('/nuevo-libro',
        {
            templateUrl:'src/views/nuevo-libro.html',
            controller: 'LibrosFichaCtrl'
        })
        .otherwise( {redirectTo: '/listado'});
    }
);


$routeParams

$routeParams nos permite recoger parámetros de la url. Requiere el módulo ngRoute también.

Para ello en la ruta lo definimos mediante dos puntos y el nombre del parámetro :libroId

var uazonApp = angular.module("uazonApp",['ngRoute','libros'])
.config(
    function($routeProvider)
    {
        $routeProvider
        .when('/ficha-libro/:libroId',
        {
            templateUrl:'src/views/ficha-libro.html',
            controller: 'LibrosFichaCtrl'
        })
    }
);

En el controlador la forma de recuperar ls parámetros $routeParams es inyectando $routeParams:

angular.controller("LibrosFichaCtrl",['$scope','$routeParams',function($scope,$routeParams) {
    $scope.libroId = $routeParams.libroId;
}]);



URLs bonitas sin # gracias a HTML5

Si queremos evitar el # podemos activar el modo HTML5 en las rutas evitando así el refresco de página. Para este cometido tendremos que realizar dos tareas:

  • Configurar $locationProvider accediendo a la variable $locationProvider de ngRoute e indicando que esta en html5 $locationProvider.html5Mode(true);
var miApp = angular.module("miApp",['ngRoute'])
.config(
    function($routeProvider, $locationProvider)
    {
        $routeProvider
        .when('/pagina1',
        {
            templateUrl:'paginas/pagina1.html',
        })
        .when('/pagina2',
        {
            templateUrl:'paginas/pagina2.html',
        })
        .otherwise( {redirectTo: '/pagina1'});

        //elimina # de la navegación
        $locationProvider.html5Mode(true);
    }
);
  • Definiendo la base de nuestro index.html <base href="/">
<html ng-app="miApp">
    <head>
        <base href="/">
    </head>
    <body>
        ...
    </body>
</html>


.htaccess

Un detalle importante es que aplicando estas dos tareas embelleceremos nuestras urls pero si copiamos la URL y la pegamos en otra ventana del navegador la aplicación no funcionará porque el servidor (en este caso Apache) pensará que es una ruta URL normal.

Por ejemplo midominio.com/pagina1 da un error de página no encontrada. Sin embargo si introducimos midominio.com/#/pagina1 si se accede a la aplicación y AngularJS modifica la URL dejándola en la deseada midominio.com/pagina1

Por eso para conseguir que incluso la URL sin # funcione al copiar y pegar esta URL en un navegador hay que hacer un pequeño hack en la configuración del.htaccess de Apache de manera que cuando llegue una URL nueva siempre siempre se sustituya por la URL con hashtag # que AngularJS la entienda y así pueda ser la propia aplicación la que le quite de nuevo el # embellecendo perfectamente la dirección URL.

.htaccess

    <IfModule mod_rewrite.c>
        RewriteEngine On
        RewriteBase /
        RewriteCond %{REQUEST_FILENAME} !-f
        RewriteCond %{REQUEST_FILENAME} !-d
        RewriteRule ^(.*)       /index.html/#/$1 
    </IfModule>


    RewriteEngine On
RewriteBase / 
RewriteCond %{REQUEST_FILENAME} !-f 
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)       /#/$1  [R=301,NE,L]