Dans cet article, nous allons expliquer le fonctionnement et l’utilité des routeurs de Backbone.js. Nous reprendrons le code de l’article Débuter avec Backbone.js comme base.
Les utilisateurs de notre application peuvent déjà naviguer en cliquant sur les différents noms de contact, mais ça se résume à ça.
On voudrait pouvoir faire en sorte que chaque contact ait sa propre URL, de façon à pouvoir y accéder directement par un lien.
C’est là l’utilisation principale des routeurs : fournir une gestion des URLs à notre application JavaScript.
Ce mécanisme se fait en priorité grâce à l’History API
pour les navigateurs la supportant, ou en dégradant vers des hash fragments
(#un/chemin
) si ce n’est pas le cas.
Dans notre précédente version du code, nos différents composants n’étaient pas
namespacés, vous pouvez récupérer sur le dépôt GitHub une nouvelle
version du code ou tous les composants sont dans un namespace app
.
Ceci nous facilitera le travail par la suite, et c’est une bonne habitude à prendre dans vos développements.
Dans notre cas, nous souhaitons avoir deux types d’URLs :
contacts/:id
qui permet d’avoir un lien direct vers la fiche d’un contact ;contacts/search/:pattern
pour avoir un lien vers le résultat d’une
recherche.Afin d’implémenter cela, on va ajouter un routeur à notre application et modifier quelques vues.
Dans un fichier js/routers/application_router.js
, on écrit le code suivant :
var app = app || {};
app.ApplicationRouter = Backbone.Router.extend({
routes: {
"contacts/search/:pattern": "filterContact",
"contacts/:id": "showContact",
},
showContact: function(id) {
var contact = app.Contacts.get(id);
app.MainView.showContact(contact);
},
filterContact: function(pattern) {
app.MainView.contactList.filter(pattern);
}
});
Décortiquons ce code !
On déclare tout d’abord un ensemble de routes, en utilisant une notation similaire à celle utilisée pour les évènements dans les vues.
La notation est assez classique, surtout si vous avez déjà fait du Rails ou du
Sinatra. Les parties de l’URL précédées d’un :
permettent de spécifier les
parties variables de nos URLs.
Notez qu’on peut très bien déclarer contacts/:id
en premier sans craindre
qu’elle prennent le dessus sur contacts/search/:pattern
car les portions
variables ne peuvent pas contenir de /
.
Chaque route est liée à une méthode de notre routeur.
Chaque méthode doit permettre de placer l’application dans l’état correspondant à la route affichée.
Ici chaque méthode appelle simplement les méthodes déjà implémentées de nos vues.
Dans notre fichier index.html
, on ajoute une ligne pour charger le fichier du
routeur après les autres déclarations <script>
, puis on modifie la partie qui
initialise l’appliation comme suit :
var app = app || {};
$(function() {
app.Contacts = new app.ContactBook();
app.MainView = new app.AppView(app.Contacts);
app.Router = new app.ApplicationRouter();
Backbone.history.start();
});
Note : nous avons changé le nom de certains composants pour améliorer la lisibilité du code
On initialise donc simplement notre routeur puis on appelle
Backbone.history.start
.
Cette dernière va analyser l’URL courante du document et faire appel au routeur pour lancer les actions adéquates.
Vous pouvez passer à start
l’argument {pushState: true}
pour utiliser
l’History API. Nous ne le faisons pas dans notre cas car l’application n’est pas
servie correctement par un domaine mais accédée via une URL file//
. L’History
API n’est pas compatible avec ce mode d’ouverture des fichiers.
Si vous lancez l’application maintenant, vous ne remarquerez aucun changement notable car on ne définit jamais l’URL correspondant à une partie de l’application. C’est donc ce que nous allons ajouter maintenant.
Une URL correspond en fait à un état de l’application.
Ici on va changer d’URL à l’affichage d’un contact et à la modification du champ de recherche.
Pour définir l’URL on utilise Router#navigate
en passant l’URL en argument.
Notre routeur étant stocké dans app.Router
, on modifie les méthodes
AppView#showContact
et ContactListView#filter
en conséquence :
// js/models/app_view.js
showContact: function(contact) {
app.Router.navigate('contacts/' + contact.id);
// ...
},
// js/models/contact_list_view.js
filter: function(contact) {
app.Router.navigate('contacts/search/' + encodeURIComponent(text));
// ...
},
Ainsi, à chaque appel de ces méthodes, l’URL sera définie automatiquement.
Vous pouvez maintenant relancer l’application et observer comment la barre d’adresse est modifiée à chaque sélection d’un contact ou à chaque modification du champ de recherche.
Vous pouvez aussi copier l’adresse et l’ouvrir dans un nouvel onglet : vous arriverez alors directement au même endroit de l’application.
Le routage dans Backbone est très léger mais très puissant, tout comme on a l’habitude avec le reste de cette bibliothèque.
L’exemple présenté ici est évidemment simple, mais vous pouvez maintenant essayer de rajouter des fonctionnalités à ce carnet d’adresses pour exploiter pleinement les fonctionnalités de Backbone.
Dans le prochain article, nous ajouterons un vrai backend à notre application.