AngularJS : directives et composants

This entry was posted by on Lundi, 25 juin, 2012 at

La notion de directive est la fonctionnalité la plus intéressante de ce framework. C’est aussi celle qui se rapproche le plus de nos framework web en Java : la création de composants réutilisables.

Une directive permet de (re)définir des balises HTML et ainsi étendre le langage jusqu’à lui donner les propriétés d’un DSL (Domain Specific language). AngularJS fourni un ensemble de directives de base pour concevoir une application web.

La manière de déclarer une directive peut varier pour permettre de s’adapter aux règles d’écriture du HTML (XHTML, XHTML strict, etc). Du coté déclaration en JavaScript la syntaxe utilisée est la même qu’en Java (CamelCase) : maBalise qui se déclinera du coté du code HTML en 5 syntaxes possibles ma:balise, ma_balise, ma-balise, x-ma-balise, data-ma-balise. L’appel pourra être fait en tant que balise, attribut ou classe CSS :




Ci-dessous un exemple d’utilisation des directives de base ng-repeat et ng-include, dont le nom indique bien la fonction. A partir de 2 templates, ici définis via la balise script mais qui aurait tout aussi bien pu être des fichiers HTML, on parcourt un tableau qui affiche ces templates et embarque des paramètres. Notez que les paramètres sont embarqués par l’héritage des propriétés du scope (voir l’article précédent).

  • La directive ng-include transforme un bout de code HTML en un composant réutilisable.
  • AngularJS permet de composer les directives entre elles et de les imbriquer.

Le plus amusant reste la création de ses propres directives pour inventer ses propres balises. C’est vraiment l’originalité de ce framework et qui de plus rend un code lisible et bien structuré.
Commençons simplement par améliorer un input en lui donnant la capacité d’autocompletion en utilisant l’autocomplete de jQuery-ui.

Pour appliquer la directive AngularJS utilise un “compilateur“. Celui-ci parcourt l’arbre DOM au démarrage. Dès qu’il détecte une directive il l’associe au noeud. Une fois toutes les directives détectées pour un noeud, la méthode compile() de chaque directive est exécutée selon sa priorité. La méthode compile() retourne une fonction link() dont l’objectif est de définir les interactions évènementielles avec l’élément et de faire le lien avec le scope (donc le modèle) via la méthode $watch.

Allons plus loin maintenant en définissant notre propre balise. Partons d’un besoin issu de notre application de gestion du dossier patient à l’hôpital : avoir un composant de recherche de patient dans un service qui permettrait aussi d’aller chercher un patient dans les autres services. L’excellent composant select2 améliore la balise select de base en lui ajoutant un champ de recherche et correspond donc parfaitement. Avec la directive on va maintenant pouvoir créer une balise dédiée. Appelons la finder et donnons lui 3 attributs :

  • data : pour passer le tableau d’objets
  • selection : pour définir la variable qui va récupérer l’objet sélectionné
  • favorite : pour indiquer le critère différenciant les patients du service des autres

L’objectif est que les patients du service s’affichent dans la liste déroulante et que les autres ne soient accessibles que par le champ de recherche :

Cette fois-ci des paramètres apparaissent, faisons une brève revue :

  • restrict : pour préciser si la déclaration est l’élément (E), l’attribut (A), la class (C), le commentaire (M)
  • template : remplace la balise par le contenu renseigné
  • replace : pour dire si l’on remplace la déclaration ou pas
  • scope : pour créer un scope fils dédié à notre directive, permet de récupérer les propriétés du scope parent en utilisant ‘=’, de récupérer un attribut en utilisant ‘@’, de récupérer une fonction en utilisant ‘&’.
  • link : le code pour affecter le select2 à l’input et déclarer les évènements qui vont alimenter le modèle

d’autres paramètres existent et pour aller dans le détail je vous invite à consulter la doc.

Le code est simple, bien organisé et reste lisible. Tout est testable (on y reviendra dans un prochain article). Cette méthode de développement permet réellement d’envisager des “big app” en JavaScript.

D’autres exemples qui sont aussi formateurs :

Ainsi que les très bons screencasts de John Lindquist (évangéliste JetBrains et quand on sait qu’ils sont en train de bosser sur un IDE online …)

Comments are closed.