Les directives sont des instructions intégrées dans le DOM que vous utiliserez presque systématiquement quand vous créerez des applications Angular. Quand Angular lit votre template et rencontre une directive qu'il reconnait, il suit les instructions correspondantes. Vous pouvez créer vos propres directives, mais dans le cadre de ce cours, nous allons uniquement aborder certaines directives qui sont fournies avec Angular et qui sont extrêmement utiles.
Il existe deux types principaux de directive : les directives structurelles et les directives par attribut.
Les directives structurelles
Ce sont des directives qui, comme leur nom l'indique, modifient la structure du document. Dans ce chapitre, vous allez en découvrir deux (il en existe d'autres) : *ngIf
, pour afficher des données de façon conditionnelle, et *ngFor
, pour itérer des données dans un array, par exemple.
*ngIf
Un component auquel on ajoute la directive *ngIf="condition"
ne s'affichera que si la condition est "truthy" (elle retourne la valeur true
où la variable mentionnée est définie et non-nulle), comme un statement if
classique.
Pour une démonstration simple, ajoutez une <div>
rouge qui ne s'affichera que si l'appareil est éteint :
class="list-group-item"
style="width:20px;height:20px;background-color:red;"
*ngIf="appareilStatus === 'éteint'"
Appareil : {{ appareilName }} -- Statut : {{ getStatus() }}
type="text" class="form-control" [(ngModel)]="appareilName"
*ngFor
Lorsque l'on ajoute la directive *ngFor="let obj of myArray"
à un component, Angular itérera l'array myArray
et affichera un component par objet obj
. Pour en comprendre l'utilisation, je vous propose de modifier la façon dont votre application génère des appareils électriques.
On peut imaginer que votre application récupère, depuis un serveur, un array contenant tous les appareils et leurs états. Pour l'instant, créez cet array directement dans AppComponent
:
export class AppComponent {
isAuth = false;
appareils = [
{
name: 'Machine à laver',
status: 'éteint'
},
{
name: 'Frigo',
status: 'allumé'
},
{
name: 'Ordinateur',
status: 'éteint'
}
];
constructor() {
Vous avez un array avec trois objets, chaque objet ayant une propriété name
et une propriété status
. Vous pourriez même créer une interface ou une class TypeScript Appareil
, mais dans ce cas simple ce n'est pas nécessaire.
Maintenant la magie *ngFor
:
class="container"
class="row"
class="col-xs-12"
Mes appareils
class="list-group"
*ngFor="let appareil of appareils"
[appareilName]="appareil.name"
[appareilStatus]="appareil.status"
class="btn btn-success"
[disabled]="!isAuth"
(click)="onAllumer()"Tout allumer
Le statement let appareil of appareils
, comme dans une for loop classique, itère pour chaque élément appareil
(nom arbitraire) de l'array appareils
. Après cette directive, vous pouvez maintenant utiliser l'objet appareil
, dont vous connaissez la forme, à l'intérieur de cette balise HTML. Vous pouvez donc utiliser le property binding, et y passer les propriétés name
et status
de cet objet.
Les directives par attribut
À la différence des directives structurelles, les directives par attribut modifient le comportement d'un objet déjà existant. Vous avez déjà utilisé une directive de ce type sans le savoir : la directive ngModel
que vous avez employée pour le two-way binding, qui modifie la valeur du <input>
et répond à tout changement qu'on lui apporte. Je vais vous montrer deux autres exemples très utiles : ngStyle
et ngClass
, qui permettent d'attribuer des styles ou des classes de manière dynamique.
ngStyle
Cette directive permet d'appliquer des styles à un objet du DOM de manière dynamique. Imaginez que, pour l'application des appareils électriques, vous souhaitiez modifier la couleur du texte selon si l'appareil est allumé ou non, disons vert pour allumé, rouge pour éteint. ngStyle
vous permet de faire cela :
[ngStyle]="{color: getColor()}"Appareil : {{ appareilName }} -- Statut : {{ getStatus() }}
ngStyle
prend un objet JS de type clé-valeur, avec comme clé le style à modifier, et comme valeur la valeur souhaitée pour ce style. Ici, vous faites appel à une fonction getColor()
dans AppareilComponent
que vous allez maintenant créer :
getColor() {
if(this.appareilStatus === 'allumé') {
return 'green';
} else if(this.appareilStatus === 'éteint') {
return 'red';
}
}
Cette fonction retourne la valeur 'green'
si l'appareil est allumé, et 'red'
s'il est éteint, modifiant ainsi la couleur du texte dans le template.
ngClass
Au-delà de modifier des styles directement, il peut être très utile d'ajouter des classes CSS à un élément de manière dynamique. Comme ngStyle
, ngClass
prend un objet clé-valeur, mais cette fois avec la classe à appliquer en clé, et la condition en valeur.
Pour cet exemple, je vous propose d'appliquer des classes Bootstrap à la balise <li>
en fonction du statut de l'appareil :
[ngClass]="{'list-group-item': true,
'list-group-item-success': appareilStatus === 'allumé',
'list-group-item-danger': appareilStatus === 'éteint'}"
style="width:20px;height:20px;background-color:red;"
*ngIf="appareilStatus === 'éteint'"
[ngStyle]="{color: getColor()}"Appareil : {{ appareilName }} -- Statut : {{ getStatus() }}
type="text" class="form-control" [(ngModel)]="appareilName"
Angular appliquera donc systématiquement la classe list-group-item
, et selon le contenu de la variable appareilStatus
, appliquera l'une ou l'autre des deux autres classes. Vous pouvez bien évidemment créer vos propres classes et les utiliser ; j'ai simplement choisi des classes Bootstrap pour simplifier l'explication.