AngularJS : navigation et routage

Principe déjà bien connu dans les frameworks web de tous type, la notion de routage permet d’associer une URL à une ressource (page web dynamique ou statique). En restant sur la même ligne, AngularJS propose une construction d’URL permettant de pointer à un endroit précis de son application : le « deep-linking ». La directive ng-view permet de charger des vues, chaque vue étant associée à une URL. La page principale devient alors le template principal et charge, au niveau de la directive ng-view, la vue correspondant à l’URL.

Déclaration des routes

La déclaration des routes se fait via les services $routeProvider et $route en utilisant la méthode config() du module :

2 routes sont ici déclarées pointant chacune vers une vue : une pour afficher une liste d’amis (/list), une autre pour éditer/créer un ami (/edit).

Il n’est pas encore possible de définir plusieurs directives ng-view dans une même page, mais le débat est ouvert. En attendant la directive ng-include permet de palier ce manque et peut être déclarée plusieurs fois dans une même page, reste par contre à gérer soi-même la dynamique d’affichage.

Le service $location

La construction d’URL est compatible avec la recommandation HTML5 History API via l’objet $location. L’idée est qu’au travers de cet objet, un code unique permet de s’adapter suivant si l’on cible des navigateurs compatibles ou pas avec cette API. Par défaut le mode HTML5 n’est pas activé, la méthode html5Mode(true) du service $locationProvider permet de le configurer. Pour avoir plus d’informations sur les 2 modes possibles, suivez le guide.
Dans l’exemple ci-dessus, $location est utilisé pour rediriger l’utilisateur vers la liste d’amis après avoir cliqué sur « Enregistrer » (voir controllers.js) :

Paramètres

Des paramètres peuvent aussi être ajoutés aux URLs. Toujours dans l’exemple ci-dessus, le lien « Editer » fait référence à l’index du tableau en paramètre de l’URL.

et la route est déclarée telle que :

Le service $routeParams vient alors s’ajouter pour donner accès aux paramètres de l’URL.
Soit pour l’URL http://server.com/index.html#/Chapter/1/Section/2?search=moby
et la route: /Chapter/:chapterId/Section/:sectionId
$routeParams renverra {chapterId:1, sectionId:2, search:’moby’}
Dans notre exemple $routeParams est injecté dans le controller FriendEditCtrl

Initialisation et temporisation avant l’affichage d’une page

La méthode de configuration d’une route $routeProvider.when(path, route) décrit la route selon un chemin (ex: /edit) auquel est associé un controleur et un template. Une route peut aussi être un redirection vers une autre URL (redirectTo). Mais il est aussi possible de paramétrer des actions à réaliser avant le chargement de la page via le paramètre resolve. Ainsi si une page doit charger une liste importante de données, ce système permet de faire patienter l’utilisateur avant l’affichage de la page. L’exemple ci-dessous est le même que le précédent à la différence que le tableau d’amis met 2s à arriver.
Pour simuler cela j’utilise dans cet exemple le service $q qui est une implémentation du modèle promise/deferred inspiré par le projet Q de Kris Kowal combiné avec le service $timeout pour déclencher la résolution de l’objet déferré 2s plus tard.
La spécificité du paramètre resolve est qu’il attend une map où chaque clé est considérée comme une référence à un service qui peut donc être injectée dans le controleur et que la valeur contient le service correspondant. Si la valeur retourne un objet « promise » alors celui-ci est résolu avant que le controleur soit instancié et émet l’évènement $routeChangeSuccess après la résolution de l’objet déférré.
=> appuyez sur le bouton play pour voir le comportement : une message « Loading friends … » apparaît pendant 2s puis la liste d’amis s’affiche

Evènement

Notez dans cet exemple l’utilisation des évènements $routeChangeStart et $routeChangeSuccess au niveau de la directive butterBar.

Celles-ci permettent d’intéragir dans le cycle d’affichage des vues et ici afficher un message en attendant l’affichage de la page.