Recursive *ngFor avec Angular

angular directives

Vous savez certainement déjà tous comment effectuer une iteration de tableau avec la directive *ngFor. Dans cet article, je vais vous montrer comment effectuer une boucle récursive avec Angular. Je vais vous présenter deux manières d’effectuer cette opération. Libre à vous ensuite de choisir celle qui convient le mieux à votre cas d’utilisation.

Avant de ce lancer dans le vif du sujet, je fais vite un mini-rappel sur l’iteration de tableau avec Angular histoire de tous avoir la même vision s de la chose.

<ul>
  <li *ngFor="let item of items">{{item|json}}</li>
</ul>

Simple, efficace et rapide à mettre en place. Maintenant nous allons attaquer la partie intéressant…

Les boucles recursives avec ng-template et ng-container

<h1>List Recusrive with Angular Structural Directives</h1>
<ul>
  <ng-template #recursiveList let-list>
    <li *ngFor="let item of items">
      {{item?.name}}
      <ul *ngIf="item?.children?.length > 0">
        <ng-container *ngTemplateOutlet="recursiveList; context:{ 
         $implicit: item.children
        }"></ng-container>
      </ul>
    </li>
  </ng-template>
  <ng-container *ngTemplateOutlet="recursiveList; context:{ $implicit: items }"></ng-container>
</ul>

Voilà un bel exemple de liste récursive.. Mais comment cela fonctionne?? Aller on regarde de plus près le fonctionnement de ce bout de code.

Fonctionnement de NgTemplateOutlet

Vous avez pu constater l’utilisation d’une directive Angular nommée NgTemplateOutlet… que fait cette directive?? À quoi sert-elle? Comment fonctionne-t-elle? Aller on check ça!

La directive NgTemplateOutlet permet d’insére une vue intégrée à partir d’un TemplateRef préparé.

Cela va nous être utile pour concevoir la structure que l’on veut boucler. En premier on définit une structure HTML qui contient deux elements distincts:
– ng-template (doc Angular NgTemplate )
– ng-container (doc Angular NgContainer)

Dans la partie « ng-template » on définit la structure HTML qui devra être générée par Angular lors du parcours de la liste d’elements. On n’oublie pas de référencer ce bout de template avec une référence Angular (templatRef) et on remarque au passage que ce bout de code contient également une directive structurelle NgContainer.

La partie « ng-container » est un élément de regroupement qui n’interfère pas avec les styles ni la présentation. On lui passe avec la directive NgTemplateOutlet, la référence de template à générer et le tableau de data dont il doit effectuer le traitement.

Astucieux non? Avec cette technique vous pouvez générer dynamiquement des loops récursives directement dans vos templates Angular.

Créer un Dump Component Angular

On pourrait s’arrêter là mais on n’est pas du genre… On peut encore aller plus loin et se dire que ce bout de code est dégeu et que cela pourri notre beau fichier template. On peut alors remédier à cela en créant un dump Component qui va effectuer l’opération du recursive loop. On aura alors un code beaucoup plus clean et lisible. C’est partit pour la mini démo:

@Component({
  selector: 'recursive-list',
  template: `
     <div *ngFor="let item of items">
      <ul>
       <li>
         {{item.name}}
         <recursive-list [items]="item.children" *ngIf="item.children"></recursive-list>
       </li>
      </ul>
    </div>
  `,
})
export class ReccursiveListComponent {
  @Input() items;
}

Ce dump component effectue la récursivité de la liste en c’appelant lui-même… Etrange mais cela fonctionne! Le component se connaît lui-même et est donc capable de boucler sur lui-même. On utilise ce component dans le template d’un autre component comme ceci et la magie opère:

<h1>List Recusrive with Angular Dump Component</h1>
<recursive-list [items]="itemsPost"></recursive-list>

Super lisible et facile à maintenir. On peut même récupérer ce component pour l’utiliser dans un autre projet vu que c’est un dump Component.

Sur ce j’espère que cet article vous a plu. N’hésitez pas à aller regarder les autres articles traitant du même sujet dans la section Angular

Et si vous avez besoin de support pour votre projet, je vous invite vous rendre sur le lien suivant pour définir ensemble une solution de support qui vous convienne.