Je viens d’effectuer la migration, de ngRoute (le gestionnaire de route par défaut d’angular) vers UI Router, le router fournit par le projet Angular UI (je vous conseille de regarder les différents modules qui peuvent être très pratique).
Le router fournit de base par Angular a quelques limitations et peut être pénalisant pour des applications complexes (Il a d’ailleurs été retiré d’Angular pour en faire un module à part depuis la version 1.2. La version 2.0 d’Angular devrait améliorer ce dernier et combler ses lacunes).
UI Router apporte notamment :
- la gestion des vues imbriqués
- Vues Multiples
- resolve imbriqués
- des directives
- ui-sref pour la génération des liens
- ui-sref-active pour ajouter une classe si un état est actif
- des callbacks onEnter et onExit
Voici un petit tutoriel/retour d’expérience pour effectuer la migration vers UI Router. Dans mon cas, cela s’est très bien passé 🙂 ).
Migration
Installation
Le plus simple est d’installer angular-ui-router via bower avec la commande suivante :
bower install angular-ui-router --save
Il faut ensuite inclure le script dans votre page (pensez à supprimer l’inclusion du script de angular-route et à le supprimer de bower)
<script src="libs/angular-ui-router/release/angular-ui-router.js"></script>
Il faut également injecter la dépendance ui-router dans votre application (et supprimer celle de ngRoute)
angular.module('volleyApp',['ngRoute','angularCharts','ui.bootstrap'])
devient donc
angular.module('volleyApp',['ui.router','angularCharts','ui.bootstrap'])
ng-view est également à remplacer par ui-view.
<div ng-view></div>
Devient
<div ui-view></div>
Gestion des routes
Dans votre fichier de configuration des routes :
app.config(function ($routeProvider) { $routeProvider .when('/', { templateUrl: 'views/home.html', controller: 'HomeCtrl' }) .when('/todo', { templateUrl: 'views/todo.html', controller: 'TodoCtrl' }) //vos autres routes ... .when('/histo/stat/:matchId', { templateUrl: 'views/stat.html', controller: 'StatCtrl' }) .otherwise({ redirectTo: '/' }); });
devient
app.config(function ($stateProvider, $urlRouterProvider) { //Set default route $urlRouterProvider.otherwise('/'); //Declare states $stateProvider .state('home', { url : '/', templateUrl: 'views/home.html', controller: 'HomeCtrl' }) .state('todo', { url : '/todo', templateUrl: 'views/todo.html', controller: 'TodoCtrl' }) //autres routes ... .state('stat', { url : '/histo/stat/:matchId', templateUrl: 'views/stat.html', controller: 'StatCtrl' }); });
Comme vous pouvez le voir, il n’y a pas grand à faire ici :
- injecter les providers $stateProvider et $urlRouterProvider à la place de $routeProvider
- Définition de la route par défaut via $urlRouterProvider.otherwise
- remplacer when par state et donner un nom de vue (qui sera utiliser plus tard lors de l’utilisation de ui-sref)
- rajouter un paramètre url pour chaque state.
Récupération des paramètres des routes
Dans ma vue de consultation des statistiques d’un match, j’utilise un paramètre dans l’url pour récuperer le match à consulter.
angular.module('volleyApp') .controller('StatCtrl', ['$scope', '$routeParams'] function ($scope, $routeParams) { $scope.matchId = $routeParams.matchId;
Devient
angular.module('volleyApp') .controller('StatCtrl', ['$scope', '$stateParams'] function ($scope, $stateParams) { $scope.matchId = $stateParams.matchId;
Ici non plus rien de très complexe. On injecte $stateParams à la place de $routeParams et on l’utilise.
Utilisation de ui-sref et ui-sref-active
UI Router fournit la directive ui-sref permettant la gestion des url.
<a class="btn btn-primary" href="#/histo/stat/{{$index}}>Stats</a>
Devient
<a class="btn btn-primary" ui-sref="stat({matchId: $index})>Stats</a>
Vous remarquerez que l’on utilise le nom du state vers lequel on souhaite être redirigé et que l’on passe les paramètres de l’URL via un objet.
ui-sref-active permet de d’ajouter des classes si l’état est sélectionné. Mon menu de navigation devient donc :
<nav> <ul class="nav nav-pills black"> <li ui-sref-active="active"><a id="homeMenu" ui-sref="home">Home</a></li> <li ui-sref-active="active"><a id="matchMenu" ui-sref="match">Match</a></li> <li ui-sref-active="active"><a id="matchMenu" ui-sref="histo">Historique</a></li> <li ui-sref-active="active"><a id="todoMenu" ui-sref="todo">Todo</a></li> </ul> </nav>
Karma
Si vous avez généré votre projet avec yeoman et que vous utilisez les tests unitaires avec karma, il faut également effectuer quelques changements :
- Remplacer l’inclusion du angular-route.js par angular-ui-router.min.js dans la partie files du fichier karma.conf
- Remplacer dans vos fichiers de tests l’utilisation de $routeParams par $stateParams.
Liens
- Le guide de démarrage rapide et le guide complet de UI Router
- Un article concernant les avantages de UI Router et les possibilités qu’il offre