jeudi 31 octobre 2013

Scope isolé dans les directives AngularJS


Second sujet que j'ai traité au Meetup chez Google, il s'agit des scopes isolés dans les directives.  Les slides se trouvent ici, et une vidéo a été mise en ligne là ; mon intervention commence par un sujet sur l'usage des services, et celui-ci est à la suite.

Le scope isolé est un outil bien pratique mis à notre disposition par AngularJS pour faciliter la création de widgets. Mais il ne faut pas l'utiliser n'importe quand, ni en faire n'importe quoi.


L'arbre des scopes


Les scopes d'AngularJS sont des objets qui servent de contexte d'évaluation des expressions contenues dans les templates.

Ils forment un arbre, dont la racine est le seul scope de l'application qui est aussi publié comme un service, sous le nom $rootScope. Ce $rootScope est associé à l'élément contenant toute l'application AngularJS, celui sur lequel on met la directive ngApp : ça peut être l'élément <html> lui-même, ou le <body>, ou un <div> à l'intérieur, peu importe.

samedi 26 octobre 2013

Services ou événements dans l'optique des tests

Quelques réflexions complémentaires à mon article sur l'usage des services, qui partent d'une question que l'on m'a posé à la fin de ma présentation au Meetup AngularJS Paris chez Google. Quelqu'un m'a demandé si les événements pouvaient être utilisés pour simplifier les tests unitaires d'un contrôleur. En limitant les injections de services en dépendances, on évite la nécessité de versions factices (mock objects) de ces services.

Cette question me turlupinait dans le trajet retour, et j'ai essayé de pousser plus loin la réflexion en explorant cette piste et diverses alternatives.

mercredi 23 octobre 2013

Usage des services AngularJS

Cet article est basé sur la présentation que j'ai faite hier au Meetup AngularJS Paris chez Google. Les slides se trouvent ici, et une vidéo a été mise en ligne là. Mais comme les slides perdent beaucoup de leur intérêt sans les explications qui vont avec, ça méritait bien un article - et même plusieurs, puisque j'ai mis deux exemples dans des articles séparés (les liens sont vers la fin). Je vais aussi en écrire un sur l'autre partie de ma présentation, sur les scopes isolés dans les directives.

S'il y a une fonctionnalité que les développeurs qui débutent sur AngularJS sous-estiment énormément, c'est bien les services. Je me rend compte régulièrement en formation ou lors d'audits que beaucoup de code pourrait être largement simplifié en utilisant plus efficacement les services. Ça n'a d'ailleurs rien d'étonnant, on commence à partir des exemples qu'on trouve sur internet, qui sont des exemples courts et n'ayant évidemment pas toute la structure d'une vraie application. Des exemples qui montrent comment ça marche, pas comment il faut faire.

Dans une application non triviale, au moins 90 % du code JavaScript devrait être dans les services. Il peut y avoir quelques directives et filtres bien sûr, dont une partie peut d'ailleurs être commune à plusieurs applications, mais ce sont les contrôleurs qui doivent être aussi réduits que possible. Un contrôleur AngularJS est juste une fonction d'initialisation du scope correspondant, et il doit essentiellement se limiter à cela : faire quelques affectations dans l'objet scope. Il ne doit pas faire de requêtes HTTP, ni des traitements sur les données, ni gérer le stockage des données.


Conserver les valeurs des critères de recherche

Comment conserver lorsque l'on change de vue à l'intérieur d'une application AngularJS des données correspondant à l'état de la vue, comme les valeurs des critères d'une recherche ?

Imaginons qu'on affiche dans une vue une liste d'objets, avec des critères permettant de faire un filtrage en local. Et sur chaque objet, un lien permet de naviguer vers une vue des détails de l'objet. Quand l'utilisateur revient sur la liste, il s'attend à la retrouver dans le même état. Ça suppose que les valeurs de filtrage saisies soient conservées.

Or si ces valeurs sont simplement dans le scope de la vue, elles seront perdues à chaque changement de vue, car le scope de l'ancienne vue est détruit par AngularJS. La solution simple pour les conserver est de les stocker dans un service.

Service AngularJS de notification

Un autre exemple de service qui peut être très utile : il s'agit d'afficher des notifications pendant quelques secondes, comme le font les applications de Google, avec un lien dans le message permettant d'annuler l'action.

C'est typiquement le genre de truc qu'on imagine compliqué, mais si on le prend bien, avec AngularJS ça s'écrit en quelques lignes - enfin sans compter le CSS qui finalement est le plus gros du boulot.

L'exemple se trouve ici sur GitHub, et il y a un lien vers la démo (c'est le même que pour l'article "Conserver les valeurs des critères de recherche"). Ajoutez des articles au panier, et quand vous en supprimez du panier, vous avez une notification avec un lien pour annuler l'action.

lundi 14 octobre 2013

Validateur pour vérifier qu'une date est postérieure à une autre

Voici un exemple de validateur spécifique, qui répond au besoin classique de vérifier que la date saisie dans un champ est postérieure à celle saisie dans un autre champ du formulaire. Typiquement, on demande de saisir une date de début et une date de fin, et on veut s'assurer qu'un utilisateur étourdi n'a pas rentré une date de fin qui précède la date de début.

L'exemple est intéressant, car il permet de voir comment valider un champ par rapport à un autre, ce qui n'est pas expliqué dans la documentation d'AngularJS.