Lorsqu’on travaille avec Angular, et que l’on souhaite passer des informations entre routes, il existe plusieurs moyens. On peut par exemple penser au passage de paramètre GET, comme une url MPA normale. Un autre moyen est le passage de paramètre via l’attribut data de chaque route. Nous verrons aussi le passage de paramètre dynamique.
Découvrons ensemble comment bien passer des données entre routes dans Angular.
Déclaration de notre routing
Créons d’abord deux composants qui vont être appelés via un menu.
ng g c features/games/new-game –standalone=true
Remarquons ici la création d’un SCAM façon angular 14.
On en crée un second.
ng g c features/games/existing-game –standalone=true
Et créons notre composant Home où nous aurons notre menu.
ng g c features/general/home –standalone=true
Dans le composant Home, ajoutons notre menu :
<header>
<div class="menu">
<ul>
<li><a routerLink="/">Accueil</a></li>
<li><a routerLink="new">Nouvelle partie</a></li>
<li><a routerLink="reload">Charger une partie</a></li>
</ul>
</div>
</header>
<router-outlet></router-outlet>
Et préparons nos routes, dans le app-routing. (note: normalement, dans un vrai projet, nous passerions par des routes par feature module)
const routes: Routes = [
{
path: '',
component: HomeComponent
},
{
path: 'new',
component: NewGameComponent
},
{
path: 'reload',
component: ExistingGameComponent
},
];
Passage de data à une route
Maintenant, admettons que nous souhaitons passer une information de configuration à une route.
Prenons par exemple des données pour le new game.
Ici, nous allons passer la configuration par défaut de notre jeu.
Tout d’abord, nous allons créer un type : Config, qui va être utilisé pour la compilation TypeScript.
Nous l’ajoutons dans le dossier shared/data/config-game.ts
export type ConfigGame = {
lifePoints: number
};
Et définissons au même endroit, une fabrique qui renvoie une valeur par défaut :
export function getDefaultGameConfig(): ConfigGame {
return {
lifePoints: 100
};
}
Nous allons pouvoir utiliser cette configuration pour notre route de Nouvelle partie, avec l’attribut data.
{
path: 'new',
component: NewGameComponent,
data: getDefaultGameConfig()
},
Et le récupérer dans notre composant !
public config$ !: Observable<any>;
constructor(private readonly route: ActivatedRoute) { }
ngOnInit(): void {
this.config$ = this.route.data;
}
Notons ici que nous avons une observable en retour, et non une donnée statique, directement.
Nous allons pouvoir l’utiliser sur le Template avec un pipe async.
<div *ngIf="this.config$ | async as config">
<b>Config : {{ config.lifePoints }}</b>
</div>
Nous pouvons aussi les récupérer sans passer par l’observable :
this.configSnapshot = {
lifePoints: this.route.snapshot.data["lifePoints"]
};
Maintenant que nous avons récupéré notre configuration, nous souhaitons pouvoir passer des datas d’une route à une autre.
Comment faire ?
L’attribut data est static, nous ne pouvons pas le modifier.
Passage de data entre component avec le state
Ajoutons un bouton pour aller vers le composant de chargement d’une partie existante.
goToReload(): void {
this.router.navigate(['reload'], );
}
<button (click)="goToReload()">Go to reload</button>
Utilisons maintenant le state pour transmettre des infos d’une route à une autre, pour communiquer à notre composant :
goToReload(): void {
this.router.navigate(['reload'], { state: { game: 1, finish: true } });
}
Ajoutons un nouveau model, dans le feature module : GameState.
export interface GameState {
game: number,
finish: boolean
}
Nous pouvons alors récupérer notre état grâce à l’injection de la Location.
constructor(private readonly route: ActivatedRoute, private location: Location) { }
Et récupérer le state :
ngOnInit(): void {
const state = this.location.getState()
}
Nous utilisons une fonction custom Type Guard : hasKey
ngOnInit(): void {
const state = this.location.getState();
if (typeof state == 'object' && state != null && hasKey('finish', state)) {
this.lastGame = state as GameState;
}
}
Note: ici, nous castons en GameState, mais on n’a pas vraiment besoin de hasKey pour ça. hasKey nous permet de construire un objet avec la propriété qu’on vérifie (ici, le finish) !
Et le tour est joué, une fois affiché !
Pour information, ici, on va utiliser en fait la partie History de notre navigateur.
La partie state d’Angular n’est qu’un proxy de ce que propose nativement js dans notre browser.