En bonne fashion victim, je suis aujourd’hui convaincu qu’une bonne architecture est une architecture distribuée ; à tel point qu’aujourd’hui mon premier réflexe est souvent de créer une API, et ce quelque soit l’ampleur du projet dans lequel je me lance.

Évidemment, je tente de réflechir à la pertinence de ce choix ; mais bien souvent le constat est le même : ce n’est pas nécessairement plus long, et les perspectives d’évolution sont immédiatement plus importantes (applications mobiles, changement de technos, mises à jours aisées, etc.).

Et avec une architecture distribuée, quand on souhaite mettre en place un frontend Web, on a tout un tas de solutions. AngularJS en est une qui, vous le verrez, est parfaitement adaptée à cette problématique.

L’exemple qui suit détaille la création de ce petit site.

AngularJS, c’est quoi ?

AngularJS est un framework MVW (pour Model-View-Wathever) écrit en JavaScript, et s’éxecutant du côté client. Je ne ferai pas ici la liste des pours et des contres, puisqu’un bon nombre d’articles sur le net en parle déjà. Je dirais juste que l’intérêt premier que j’y vois est qu’il force à séparer de manière nette la partie visuelle et la partie traitement (bon, puis il y a aussi le binding di-directionnel, les directives HTML, les … non. J’ai dit que j’en parlerais pas.).

Concrètement, ça donne quoi ?

Ceux qui n’ont jamais eu l’occasion d’utiliser ce genre de frameworks doivent encore trouver ça trouble ; et étant moi même débutant dans ce monde, je suis bien placé pour le savoir. Je vais tenter de vous donner un exemple que j’aurais certainement aimé trouver il y a quelques mois, lors de mes premiers pas avec AngularJS.

Un exemple avec l’OpenData de Nantes

Pour illustrer cet article, je vous propose un petit exemple s’appuyant sur l’OpenData de Nantes dans lequel il sera question d’afficher les prix des parkings.

Précisions sur l’API

Avant de commencer, ne vous étonnez pas de voir que les appels sont effectués sur nicolasc.eu. En effet, le banal problème du XHR cross-domain se posait et l’encodage avait quelques soucis. J’ai donc fait un petit proxy en PHP qui se charge de récupérer le tout, de le ré-encoder en UTF-8 et de mettre les bons headers. Si vous souhaitez faire des tests sur ce proxy, sachez que les paramètres restent les mêmes. Vos URLs doivent alors se temrminer par ?filter= ; je vous laisse le soin d’aller voir la documentation pour plus de détails.

Les résultats sont renvoyés en Json et la structure ne change pas par rapport à l’API originale.

Place à l’exemple

Nous sommes maintenat prêts à démarrer notre exemple. Nous allons créer deux contrôleurs :

  • ParkingController :
    • Il sera chargé de récupérer la liste des parkings disponibles et de les envoyer à la vue. Celle-ci les affichera sous forme de tuiles.
  • TarifController :
    • Il devra être capable d’afficher la liste des tarifs correspondant au parking voulu. Les tarifs seront affichés sous forme de tableau et devront pouvoir être triés.

Vous ne tarderez plus à vous rendre compte qu’il ne faut que très peu de code pour arriver à tirer d’AngularJS quelque chose de fonctionnel.

Le point d’entrée

Dans un premier temps, il nous faut créer un fichier JavaScript qui sera la base de notre application. J’ai pour habitude de le nommer app.js. Celui-ci devra contenir nos routes, et devra préciser quelle vue afficher en fonction de quel controleur.

Notre application doit être capable de fournir les tarifs correspondant à un parking selectionné. Sous-entendu, nous auront une vue parking qui sera la page par défaut de notre site, et la vue tarif. Le fichier app.js doit alors ressembler à ça :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
var tarifsApiUrl = "http://demo.nicolasc.eu/tarifs-parkings-nantes/api/tarifs_proxy.php";
var parkingsApiUrl = "http://demo.nicolasc.eu/tarifs-parkings-nantes/api/parkings_proxy.php";

angular.module('TarifsParkings', ['ngRoute', 'ngCookies'])
.config(function($routeProvider) {
$routeProvider
.when('/', {
controller:'ParkingController',
templateUrl:'parkings.html'
})
.when('/tarifs/:name', {
controller: 'TarifController',
templateUrl: 'tarifs.html'
})
.otherwise({
redirectTo:'/'
});
})
.controller([]);

Les deux premières variables correpondent aux adresses de l’API à interroger. Ainsi, nous les définissons une bonne fois pour toute.

Nous précisons ensuite qu’il s’agit de l’application TarifsParkings à l’aide de la ligne angular.module('TarifsParkings').

Le bloc qui suit sert à configurer le router. Nous indiquons ici que lorsque le client arrive sur la racine du site, nous appellerons le contrôleur ParkingController et que ce dernier exploitera la vue parkings.html.
Même chose ensuite pour les tarifs, si ce n’est que l’URL se termine par :name. Cela indique que cette URL accepte un paramètre et qu’il se nomme name. Vous l’aurez compris, c’est ce paramètre qui nous permettra de sélectionner les tarifs du bon parking.
Le .otherwhise() nous permet de rediriger l’utilisateur sur la racine du site s’il entre une adresse non gérée.

Enfin, puisque nous séparons les contrôleurs dans des fichiers distincts, on fait apparaître .controller([]) en fin de fichier.

On doit maintenant définir une structure commune à nos différentes pages. Les vues seront par la suite incluses dans cette structure. Le fichier -que nous nommerons index.html- doit contenir ce qui suit :

1
2
3
4
5
6
7
8
9
10
11
12
13
<html ng-app="TarifsParkings">
<head>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
<script src="js/vendor/angular.js"></script>
<script src="js/vendor/angular-route.js"></script>
<script type="text/javascript" src="js/app.js"></script>
<script type="text/javascript" src="js/parkings.js"></script>
<script type="text/javascript" src="js/tarifs.js"></script>
</head>
<body>
<div ng-view></div>
</body>
</html>

Pas grand chose à détailler, si ce n’est qu’il faut préciser ici aussi le nom de l’application à l’aide de ng-app="TarifsParkings" et qu’il ne faut pas omettre d’inclure les fichiers JavaScript.

Les vues seront bien sûr incluses là où <div ng-view></div> est précisé.

La gestion des parkings

Nous souhaitons maintenant récupérer les parkings, puis les afficher dans notre vue. Le contrôleur doit alors ressembler à ça :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
angular.module('TarifsParkings')
.controller('ParkingController',
function($scope, $http, $cookieStore, $location) {
$scope.serverError = false;
$scope.parkings = new Array();

$http.get(parkingsApiUrl)
.success(function(data, status, headers, config) {
$scope.parkings = data;
$scope.serverError = false;
})
.error(function(data, status, headers, config) {
console.log("Error: " + data);
$scope.serverError = true;
});

$scope.consult = function(name) {
$location.path('/tarifs/' + name);
};
}
);

Ici aussi, le nom de l’application doit apparaître en première ligne ; suivi du nom du contrôleur.

$scope.serverError et $scope.parkings nous permet de définir deux attributs à notre modèle. Ces attributs seront ensuite exploités par la vue.

Arrive ensuite l’appel de l’API à l’aide de $http. On précise ici que la méthode HTTP à employer est de type GET, et on lui passe l’adresse de l’API spécifiée dans le fichier app.js.

Nous définissons ensuite la méthode $scope.consult. Cette dernière servira à rediriger l’utilisateur sur la page des tarifs en passant le bon nom de parking.

Nous sommes maintenant prêts à créer la vue. Celle-ci doit contenir ceci :

1
2
3
4
5
<div class="container" ng-controller="ParkingController">
<a ng-repeat="parking in parkings" ng-click="consult(parking)">
{{ parking }}
</a>
</div>

Le nom du contrôleur est alors précisé. On arrive ensuite sur un élément ng-repeat. Celui-ci agira comme un foreach(). On boucle alors sur le tableau parkings défini dans le contrôleur, et on précise que la méthode consult() doit être appelée lorsque l’on clique sur un élément. Le tout sans oublier bien sûr de passer le parking en paramètre.

Pratique, n’est-ce pas ?

La gestion des tarifs

L’opération est très semblable pour les tarifs. Je vous invite à aller y jeter un oeil directement sur GitHub. Vous apprécierez certainement la simplicité avec laquelle il est possible de trier un tableau !

Quoi qu’il en soit, une fois légèrement stylé, vous devriez arriver assez vite à ce résultat.

En conclusion

Comme on a pu le voir, AngularJS permet de produire assez rapidement un frontend propre, efficace, et capitalisable. Qu’il s’agisse de se brancher à une API existante ou d’initier un nouveau projet, avec un peu d’habitude il est possible de transformer très rapidement une idée en site Web fonctionnel ; et ça, c’est un bon point.


J’espère que cette introduction vous aura donné envie d’aller plus loin avec AngularJS. En attendant, je vous dis à bientôt ici même !