Blog ENI : Toute la veille numérique !
🐠 -25€ dès 75€ 
+ 7 jours d'accès à la Bibliothèque Numérique ENI. Cliquez ici
Accès illimité 24h/24 à tous nos livres & vidéos ! 
Découvrez la Bibliothèque Numérique ENI. Cliquez ici
  1. Livres et vidéos
  2. Angular et Node.js
  3. Angular et la gestion des routes internes
Extrait - Angular et Node.js Optimisez le développement de vos applications web avec une architecture MEAN (2e édition)
Extraits du livre
Angular et Node.js Optimisez le développement de vos applications web avec une architecture MEAN (2e édition) Revenir à la page d'achat du livre

Angular et la gestion des routes internes

Principe général du routage

1. Pourquoi mettre en place un routage ?

Angular permet de créer des applications monopages. Ces applications sont constituées de différents codes JavaScript et complètement téléchargées avant que l’internaute n’opère la moindre action (le serveur n’étant sollicité que pour échanger des données avec l’application Angular). La vue globale de l’application est donc constituée d’une composition de vues (les templates des composants), et certaines de ces vues ne doivent apparaître que temporairement lors de l’activation de certains composants. Ces activations sont faites généralement en réponse à une action de l’internaute (il est bien sûr aussi possible qu’une action de l’internaute n’active pas une vue en restant sans effet sur l’interface, mais ce cas est peu fréquent).

Le schéma transactionnel suivant est donc fréquemment mis en œuvre : une action de l’internaute réalisée au travers du template d’un premier composant déclenche un traitement opéré par un second composant et active sa vue (c’est-à-dire son template).

Dans le cadre de l’application fil rouge d’e-commerce, l’internaute peut réaliser les actions suivantes :

  • Définir les critères (type, marque, prix, popularité...) des produits dont il veut avoir des informations (via la vue du composant selectionbycriteriaComponent) : les produits répondant à ces critères sont recherchés dans la base MongoDB, puis affichés sur une vue activée à ce moment-là (et gérée par le composant productDisplayComponent).

  • Sélectionner un produit parmi ceux affichés dans la vue du composant productDisplayComponent pour l’ajouter à son panier : ce produit est ajouté dans la liste des produits du panier de cet internaute stockée dans une collection MongoDB (composant cartManagementComponent) et la vue des produits du panier apparaît (composant cartDisplayComponent).

Pour gérer ces transactions, il y a deux possibilités :

  • Soit à partir de la vue d’un premier composant, une méthode d’un autre composant...

La syntaxe des routes

Cette section dresse un portrait plus complet des routes. La directive routerlink associée aux ancres sera tout d’abord introduite dans les exemples de sélection de routes, puis la méthode navigate(), qui permet aussi d’effectuer des sélections, sera abordée.

Au plus haut niveau, la sélection d’une route interne sous Angular est généralement spécifiée par deux informations, la seconde étant facultative :

  • La route proprement dite (qui correspondrait au path d’une URL), que nous nommerons le chemin. Ce chemin absolu ou relatif comprend un ou plusieurs segments (dont certains peuvent recouvrir des paramètres).

  • Un objet JavaScript qui spécifie les outlets nommées (les auxiliary outlets) qui définissent des emplacements spécifiques (identifiés par un nom) où les vues des composants invoqués par la route sont activées. Si cet objet n’est pas présent, les vues sont redirigées vers l’emplacement par défaut : la primary outlet.

La syntaxe de la sélection des routes est ainsi conditionnée par rapport à plusieurs facteurs :

  • La route est définie en JavaScript par une chaîne ou une liste.

  • La route peut être absolue ou relative.

  • La route peut comporter des paramètres dans son chemin.

  • La route peut être associée à une auxiliary outlet.

  • La route peut être prise en charge par plusieurs tables de routage dans le cas où l’application est composée de plusieurs modules.

Dans ce qui suit, nous allons introduire l’ensemble des éléments qui influent sur la syntaxe des routes.

1. Les deux syntaxes d’une route : chaîne ou link parameters array

Si le chemin n’est constitué...

Sélection des routes

Il y a deux possibilités pour sélectionner une route (cette sélection se faisant généralement directement ou indirectement à partir d’un template) :

  • En utilisant la directive routerLink, qui est associée aux éléments HTML cliquables (par exemple, les ancres).

  • En utilisant la méthode Router.navigate(), cette méthode, étant souvent appelée directement ou indirectement à partir d’un écouteur d’événements.

La directive routerLink et la méthode navigate() de la classe Router proviennent du package @angular/router.

1. La directive routerLink

La directive routerLink, qui permet de sélectionner une route, est associée aux éléments HTML cliquables, comme les ancres.

Comme nous l’avons vu, si plusieurs éléments constituent la route (présence de paramètres et/ou de l’objet définissant les outlets de sortie), ces éléments sont regroupés dans une liste. Dans ce cas, la valeur de la directive étant du code JavaScript, le nom de la directive est encadré par des crochets : [routerLink]

Voici le schéma de programmation à mettre en œuvre :

<a [routerLink]="[...]"> ... </a> 

Voici un exemple :

<a [routerLink]="['/research', 
       ...

Gestion des routes du contrôleur vers le composant cible

Dans une application Angular, il est possible de créer des modules spécifiques dédiés au routage accompagnant le root module et les feature modules (ce n’est pas une obligation, car les configurations de routage peuvent être aussi spécifiées directement dans les codes des modules, mais cette externalisation rend plus facile la maintenance du projet). Le module AppRoutingModule qui accompagne le root module est créé par la commande ng new --routing (ce module apparaît dans le fichier app-touting.module.ts). Ce module utilise (et donc, importe) le service RouterModule (du package nodes_modules/@angular/router).

1. Configuration de la table de routage

L’application fil rouge peut utiliser une ou plusieurs tables de routage. En effet, outre la table de routage associée au root module, il y aura sans doute une table de routage par feature module.

Une table de routage est définie par la collection (une liste d’objets) de type routes. Voici le schéma de programmation (de base) où chaque objet de cette collection fait le lien entre une route et le composant à invoquer sur la sélection de celle-ci :

import { Routes, RouterModule } from '@angular/router'; 
... // importations des composants invoqués par les routes 
 
const routes :Routes = [ 
  { 
    path: <route>, 
    component: <composant à invoquer> 
  }, 
  { 
    path: <route>, 
    component: <composant à invoquer> 
  }, 
  ... 
]; 

La table de routage est fournie au routeur par la méthode forRoot() si elle concerne le root module, ou par la méthode forChild() si elle concerne un feature module.

Voici le schéma de programmation du module spécifiant la table de routage :

import { NgModule } from '@angular/core'; 
import { Routes, RouterModule } from '@angular/router'; 
... // importations des composants invoqués par les routes 
 
const routes: Routes = [ 
  ... 
]; 
 
@NgModule({ 
  imports: [RouterModule.forRoot(routes)],   
           ...

Gestion de routes dans le fil rouge

Dans le cadre de l’application fil rouge d’e-commerce, deux fonctionnalités ont été développées dans deux feature modules :

  • La sélection et l’affichage des produits à partir de différents modes de recherche (module research).

  • La gestion du panier (module cart).

Comme il a déjà été mentionné, chaque module doit posséder sa propre table de routage, ce qui permet aux feature modules d’être réutilisables. Pour améliorer la lisibilité du code, les tables de routage sont gérées dans des modules spécifiques accompagnant ces deux modules et le root module.

Le routeur gère donc trois tables de routage : une définie au niveau du root module, deux définies au niveau des feature modules.

Au niveau du root module, la table de routage du module AppRoutingModule (fichier src/app/app-routing.module.ts) permet de router les routes primaires :

  • research vers les composants du module research.

  • cart vers les composants du module cart.

Au niveau des feature modules, les tables de routage gèrent les routes secondaires :

  • La table de routage du module research est spécifiée dans le module ResearchRoutingModule (fichier research-routing.module.ts).

  • La table de routage du module cart est spécifiée dans le module CartRoutingModule (fichier cart-routing.module.ts).

Le lazy loading permet de ne charger les composants du module désigné par la route primaire qu’au moment où cette route est pour la première fois prise en charge...

Bilan des acquis de ce chapitre

Le routeur d’Angular permet d’activer un composant (et donc de faire apparaître sa vue) après qu’une route a été sélectionnée (à la suite d’une action, par exemple la sélection d’un élément cliquable d’un template). Cet affichage est temporaire, contrairement à l’affichage d’un composant dont la balise est directement insérée dans un template (il est quand même possible, mais maladroit, de conditionner un tel affichage « permanent » via la directive structurelle *ngIf).

Par ailleurs, suivant la route sélectionnée, la vue du composant activé sur une route peut apparaître à l’emplacement par défaut (la primary outlet), ou à un emplacement spécifique (dans une outlet nommée ou auxiliary outlet). De plus, le routeur peut également vérifier que des conditions particulières sont validées avant d’activer un composant.

Nous voyons ainsi toute la souplesse que procure la mise en œuvre du routeur. Et bien sûr, le découplage fort qu’il instaure entre l’expression d’une action et sa réalisation facilite l’évolution des applications et confère en partie au routeur le rôle de contrôleur du paradigme modèle-vue-contrôleur....