Les routes imbriquées sous Angular

Bonjour à tous,

Tout d’abord, non je ne suis pas mort ! 🙂 C’est juste que je n’ai trop pris le temps c’est dernier temps pour écrire. Mais je me rattrape avec cet article sur les routes sous angular7.

Mettre en place les routes « basiques » sous Angular7 est facile, il suffit de mettre dans le fichier app-routing.module.ts

, un code équivalent à : const routes: Routes = [
{path: '', redirectTo: '/login', pathMatch: 'full'},
{path: 'artists', component: ArtistComponent},
{path: 'login', component: LoginComponent},
{path: 'logout', component: LogoutComponent},
{path: '**', redirectTo: '/login'}
]

Ainsi, lorsqu’on va appeler http://localhost:4200/, on sera redirigé vers http://localhost:4200/#/login

C’est super, on a créé nos premières routes. Mais comment les utiliser ? Par exemple, lorsque l’utilisateur vient de s’authentifier, on veut le rediriger vers la page artist. Pour cela, dans la fonction de vérification d’authentification, lorsqu’elle est bonne on finit par une redirection vers artist. Le code ressemble à ça :
this.router.navigateByUrl('/artists');
Il faut noter la présence du / devant artist. Ca permet de dire qu’on recherche l’url à partir de la racine.

Ok, mais comment faire pour mettre en place des url imbriquées contenant l’id de l’artiste sélectionné ?

Déjà, l’intérêt de ce genre d’url est de pouvoir hiérarchiser les dépendances entre les différentes ressources. En gros, un artiste a un ou plusieurs albums, et chaque album a plusieurs chansons (pour faire simple). Donc, lorsqu’on est sur une chanson, on voudrait avoir une urls du style http://localhost:4200/#/artists/1/albums/3/sings/2. Comme ça, on sait qu’on a sélectionné l’artiste 1, l’album 3 et la chanson 2.

Pour mettre en place, des urls ressemblants à ça, il faut retourner dans le fichier app-routing.module.ts et mettre un code ressemblant à :
const routes: Routes = [
{path: '', redirectTo: '/login', pathMatch: 'full'},
{path: 'artists', component: ArtistComponent},
{
path: 'artist/:idArtist',
children: [
{path: '', redirectTo: 'artists', pathMatch: 'full'},
{path: 'artists', component: ArtistComponent},
{path: 'albums', component: AlbumComponent},
{path: 'albums/:idAlbum',
children: [
{path: '', component: AlbumComponent},
{path: 'sings',component: SingComponent},
{path: 'sings/:idSing',component: SingComponent}
]
}
]
},
{path: 'login', component: LoginComponent},
{path: 'logout', component: LogoutComponent},
{path: '**', redirectTo: '/login'}
];

Qu’avons nous fait ? Pour la route Artists, nous allons laissé le contrôleur, mais nous avons rajouté le fait qu’il pouvait y avoir une url de type : http://localhost:4200/#/artists/1. Dans ce cas là, le contrôleur ArtistComponent sera appelé, grâce à la ligne {path: 'artists', component: ArtistComponent},. Ca nous permettra par exemple d’afficher le détail d’un artist.
Lorsque l’url sera http://localhost:4200/#/artists/1/albums, le contrôleur AlbumComponent sera appelé, grâce à la ligne {path: 'albums', component: AlbumComponent}.
Pour appeler http://localhost:4200/#/artists/1, on pourrait imaginer que nous sommes dans un tableau qui liste tous les artistes et que pour chacun, il y a un bouton « Voir » :
<table>
<tr><th>Artiste</th><th></th></tr>
<tr *ngFor="let artist of artists">
<td>{{artist.name}}</td>
<td><a [routerLink]="['/artists', artist.id]">Voir</a></td>
</tr>
</table>

L’intérêt ici est le [routerLink]="['/artists', artist.id]". On a mis en première partie le début de l’url « /artists » et ensuite l’id qui sera injecté dans l’url construite. Ce qui nous permettra d’avoir en résultat : http://localhost:4200/#/artists/1.

De même, si nous voulons créer une url du style /#/artists/1/albums/2,
nous écririons un routerLink du style : [routerLink]="['/artists', artist.id, 'albums', album.id]".
Mais dans certains cas, nous voulons pouvoir créer ces urls directement depuis le contrôleur. Pour ce faire, il suffit d’ajouter dans le constructeur, le router: constructor(private router: Router) { }
, et là où nous voulons faire la rédirection : this.router.navigate(['/artists', artist.id, 'albums', album.id, 'sings', sing.id]);.
Ce qui génèrera une url ressemblant à : /#/artists/1/albums/3/sings/2

Le point d’attention de cet article se situe dans le fichier app-routing.module.ts.
En effet, souvent on trouve sur internet des tutoriels qui expliquent qu’il faut écrire un component par défaut juste avant de déclarer les enfants. Exemple :
path: 'artist/:idArtist',component: ArtistComponent,
children: [
{path: '', redirectTo: 'artists', pathMatch: 'full'},
....

En faisant ça, aucun contrôleur enfant ne sera appelé car le component par défaut interceptera toutes les requêtes commençant par « artists/… »

J’espère que cet article pourra aider certains d’entre vous et que vous n’allez pas vous embêter autant que moi pour trouver ça ! 😀