Les directives

directiveDans l'architecture Angular, les directives sont finalement partout. Les Components sont des directives à la seule différence qu'ils possèdent une fonctionnalité de templating. En TypeScript, une directive est une classe à laquelle on applique le décorateur @Directive. Il existe deux sortes de directives :

  • Les directives structurelles : Elles ont pour but de modifier le DOM en ajoutant, enlevant ou replaçant un élément du DOM. 
  • Les attribute directives : Elles ont pour but de modifier l'apparence ou le comportement d'un élément.

Les directives structurelles

Je ne vais pas lister toutes les directives structurelles proposées par Angular mais nous allons quand même en étudier une pour l'exemple : ngIf . ngIf permet de supprimer ou de recréer  l'élément courant suivant l'expression passée en paramètre. Si l'expression assignée au ngIf est évaluée à false alors l'élément sera supprimé du DOM, puis l'élément sera recréé si l'expression est évaluée à true. Voici un exemple de template utilisant cette directive :

 

 

Afficher la div sera bien affiché puisque l'expression 1 > 0 vaut bien true. Je vous propose maintenant d'inverser le sens de l'expresssion de sorte que 1 < 0. Dans ce cas, notre div disparait totalement du DOM.

Vous vous posez sans doute la question du symbole astérisque (*) devant notre directive. Les directives structurelles telles que *ngIf, *ngFor et *ngSwitchCase sont toutes encadrées par un component <ng-template> qui se veut très proche de la balise HTML 5 <template>.  Dans la version 2 d'Angular, <ng-template> se nommait <template>, ce qui pouvait être ambiguë. L'astérisque (*) permet de lire et d'écrire plus facilement des directives qui ont vocation à changer la mise en page HTML. Prenons l'exemple de notre directive ngIf : lorsque Angular va détecter (*) devant *ngIf, il va opérer différentes transformations pour arriver au résultat suivant :

 

 

Notre directive ngIf sera donc maintenant un template HTML 5 et pourra interpréter l'expression passée en paramètre grâce au Property Binding (usage des [ ]).   

 

Les attributes directives

Une bonne candidate pour comprendre les attribute directives est la directive ngStyle. Cet attribute directive se charge de modifier l'apparence de l'élément porteur. Lorsque l'on utilise cette directive, il est nécessaire de la placer entre crochets comme ceci : [ngStyle] . Ce n'est pas forcément le cas de toutes les d'attribute directives. ngStyle attend une valeur en paramètre, elle utilise ce que l'on appelle le Property Binding  que nous reverrons plus tard. Voici un exemple de template utilisant cette directive :

 

 

Dans ce cas, il n'y a pas de modification de structure. La directive transforme juste notre [ngStyle]="{color:'red'}" en style="color: red;".

 

Construire ses directives

Je vous propose maintenant de créer notre propre directive pour bien en comprendre le fonctionnement. Voici notre cahier des charges :

 

Réaliser une directive qui permet de modifier la couleur lorsque le pointeur de la souris passe dessus. 

 

A la lecture de cette spécification "post-it", une réunion a été organisée avec la maitrise d'ouvrage. Concernant la couleur, aucun compromis n'a été trouvé après 3 heures de débat même si le rouge intéressait pas mal d'intervenants. Pour contenter tout le monde, notre Directive devra proposer une couleur par défaut (le rouge) lors de l'affichage et une autre couleur paramétrable pour le mouse enter et tout cela avec le même budget.

 

A la lecture du compte rendu de cette réunion, nous pouvons déjà nous dire que nous sommes face à une attribute directives. 

 

Création de notre Directive

 

Commençons par créer notre directive à l'aide d'Angular-CLI à l'aide de la commande : 

capture-decran-2016-10-16-a-13-13-02

 

Cela nous donne le code suivant pour notre directive:

 

 

Pourquoi Angular-CLI ajoute des [ … ]  à notre sélecteur ? Angular utilise les sélecteurs CSS pour identifier l'élément HTML dans un template. Grâce à cette annotaion, Angular sera capable de localiser tous les éléments qui possèdent l'attribut nommé appHighLight.

 

La première étape consite à appliquer la couleur par défaut lorsque l'on applique cette directive. Comme nous sommes dans une classe, nous pouvons utiliser le constructeur comme ceci :

 

ElementRef est injecté dans le constructeur par Angular afin de récupérer l'élement du DOM dans notre classe. Grace à cette injection, il est possible de modifier le style de l'élement grace à Renderer2. Vous pouvez tester votre directive dans le template d'un de vos Components comme ceci :

 

 

Bon, on ne va pas se mentir, le résultat est plutôt décevant. Le texte est rouge certes, mais cela s'arrête là. On va dynamiser tout cela alors … 

Ajouter du component grâce aux events JavaScript

Notre directive doit réagir à deux évènements :

  • Lorsque le pointeur de la souris est sur l'élément : la couleur du texte doit passer à une couleur paramétrable.
  • Lorsque le pointeur de la souris quitte l'élément : la couleur du texte doit redevenir rouge.

Angular propose le décorateur @HostListener pour positionner des Listners sur l'élément. Il prend en paramètre l'évènement que l'on veut écouter. Notre classe devient alors :

 

 

A l'exécution, si l'on ouvre la fenêtre de debug JavaScript, on remarque que notre div réagit bien aux évènements  mouse enter et mouse leave.

capture-decran-2016-10-16-a-17-04-46

Il ne nous reste plus qu'à définir la couleur paramétrable grâce à un autre décorateur Angular : le décorateur @Input . Ce décorateur permet de lier le paramètre passé à une propriété de la classe de la Directive. Il est possible de passer en paramètre un alias dans le cas où la propriété de la classe n'a pas le même que l'attribut de la Directive. Voici notre Directive finale : 

 

 

Grâce à ce code, il est possible d'utiliser notre Directive comme ceci :

 

 

La classe a été un peu remaniée pour coller au besoin :

  • Le constructeur a été modifié pour permettre d'utiliser ses paramètres dans toute la classe. Le fait de mettre la portée devant les paramètres et un accélérateur de développement qui permet de faire l'équivalent d'un this._el = _el . C'est une spécificité TypeScript, et c'est bien pratique quand même.
  • Le @Input a été ajouté. Il permet de récupérer notre couleur passée en paramètre de notre directive.
  • Nos @HostListener ont été modifiés pour permettre le changement de couleur comme c'était le cas avec notre constructeur.

 

Voilà, maintenant, vous êtes prêts à faire vos propres Directives Angular !

William Koza

William Koza

Consultant Indépendant chez  
Passionné par la conception et le développement logiciel, j’ai rapidement pris le rôle de Technical Leader lors de mes premiers projets. Ces expériences ont ainsi pu me faire accéder à des rôles d’architecte dans des projets d’envergure. Aujourd'hui, j'exerce mon métier en tant qu'indépendant, et toujours avec la même passion.
William Koza

Les derniers articles par William Koza (tout voir)

  • Pingback: Les modules Angular | Learn Angular()

  • Pingback: Le Data Binding Angular 2 | Learn Angular()

  • Lmd BtsSio

    Bonjour,
    En ce qui me concerne, le changement de couleur ne fonctionne pas. On rentre bien dans les méthodes (j’ai mis un point d’arrêt), les paramètres sont bien affectés, mais le setStyle ne fonctionne pas !

    • William Koza

      Bonjour,

      Vous parlez bien du dernier exemple ? Il n’y aucune erreur au buildtime ou au runtime ?