Il est très souvent utile dans une application dynamique d'avoir accès à la route active. Ce que ça va vous permettre de faire dans ce chapitre, c'est de créer une route avec un paramètreid
pour visualiser un seul FaceSnap. Le component que vous allez associer à cette route pourra récupérer cet id
afin de demander à FaceSnapsService de lui envoyer le FaceSnap correspondant.
Commençons par créer le component qui sera, pour simplifier, une copie de FaceSnapComponent, mais avec une nuance quant au FaceSnap affiché.
Visualisez un seul FaceSnap
Générez un nouveau component appelé SingleFaceSnapComponent, et transposez-y tout depuis FaceSnapComponent : template, TS et styles.
Vous pouvez dès maintenant créer la route qui appellera ce component. Il faut que l'on puisse y passer un paramètre dynamique, c'est-à-dire le segment de la route qui contiendra l'id
du FaceSnap, et qui sera donc dynamique. Voilà comment faire :
const routes: Routes = [
{ path: 'facesnaps/:id', component: SingleFaceSnapComponent },
{ path: 'facesnaps', component: FaceSnapListComponent },
{ path: '', component: LandingPageComponent }
];
Les :id
spécifient que ce qui se trouvera après facesnaps/
correspondra à un paramètre qui s'appellera id
.
Problème ! On n'a aucun moyen de passer un FaceSnap au @Input()
de ce component ! Comment fait-on pour récupérer l'id passé en paramètre de route ?
Heureusement, nous avons une solution !
Récupérez les paramètres de route
Afin de récupérer les informations de la route activée, vous allez injecterActivatedRoute
dans SingleFaceSnapComponent, sans oublier d'enlever le décorateur @Input()
de la propriété faceSnap
:
export class SingleFaceSnapComponent implements OnInit {
faceSnap!: FaceSnap;
snapButtonText!: string;
userHasSnapped!: boolean;
constructor(private faceSnapsService: FaceSnapsService,
private route: ActivatedRoute) {}
Ensuite, dans ngOnInit()
, vous allez pouvoir récupérer le paramètre id
via le snapshot de la route (un snapshot est un aperçu instantané d'une valeur qui change au cours du temps) :
const faceSnapId = this.route.snapshot.params['id'];
Afin de pouvoir récupérer un FaceSnap par son id, je vous propose d'ajouter une méthode à FaceSnapsService, en refactorisant snapFaceSnapById par la même occasion :
// ...
@Injectable({
providedIn: 'root'
})
export class FaceSnapsService {
// ...
getFaceSnapById(faceSnapId: string): FaceSnap {
const foundFaceSnap = this.faceSnaps.find(faceSnap => faceSnap.id === faceSnapId);
if (!foundFaceSnap) {
throw new Error('FaceSnap not found!');
}
return foundFaceSnap;
}
snapFaceSnapById(faceSnapId: string, snapType: SnapType): void {
const faceSnap = this.getFaceSnapById(faceSnapId);
faceSnap.snap(snapType);
}
}
Du coup, depuis SingleFaceSnapComponent, vous pouvez appeler la méthode getFaceSnapById()
du service pour récupérer le FaceSnap correspondant à l' id
récupéré :
const faceSnapId = this.route.snapshot.params['id'];
this.faceSnap = this.faceSnapsService.getFaceSnapById(faceSnapId);
La méthode ngOnInit
commence à être un peu trop "busy", donc je vous propose d'en extraire deux méthodes privées :
// ...
export class SingleFaceSnapComponent implements OnInit {
// ...
ngOnInit(): void {
this.prepareInterface();
this.getFaceSnap();
}
// ...
private prepareInterface() {
this.snapButtonText = 'Oh Snap!';
this.userHasSnapped = false;
}
private getFaceSnap() {
const faceSnapId = this.route.snapshot.params['id'];
this.faceSnap = this.faceSnapsService.getFaceSnapById(faceSnapId);
}
}
Pour compléter l'application, et permettre à vos utilisateurs d'accéder à cette nouvelle route, je vous propose de modifier FaceSnapComponent pour n'afficher que le titre des FaceSnaps, et d'y ajouter un bouton qui permet d'ouvrir le FaceSnap dans la nouvelle route.
Du coup, le template donnera :
<div class="face-snap-card">
<h2>{{ faceSnap.title | uppercase }}</h2>
<button (click)="onViewFaceSnap()">VIEW</button>
</div>
Je vous laisse quelques instants pour tenter d'implémenter onViewFaceSnap()
, sans indice cette fois-ci.
…
…
Voilà ma solution. Il faut bien sûr injecter le Router, et utiliser sa méthode navigateByUrl()
:
// ...
export class FaceSnapComponent {
@Input() faceSnap!: FaceSnap;
constructor(private router: Router) {}
onViewFaceSnap() {
this.router.navigateByUrl(`facesnaps/${this.faceSnap.id}`);
}
}
Comme ça, votre page FaceSnaps ressemble à ça :
Et les boutons VIEW vous amènent vers les routes SingleFaceSnapComponent. Du coup, tout ce qui reste, c'est de mettre un lien ou un bouton Back dans SingleFaceSnapComponent pour permettre un retour en arrière facile, mais attention au piège !
<!-- ... -->
<h2>{{ faceSnap.title | uppercase }}</h2>
<a routerLink="/facesnaps">BACK</a>
<!-- ... -->
Avec ces dernières fonctionnalités, votre première application Angular est terminée !
En résumé
On récupère les paramètres de la route activée en injectant ActivatedRoute, et via son objet
snapshot.params
.Pour naviguer vers une route absolue (et non relative), n'oubliez pas d'ajouter un
/
au début de la route demandée.
Qu'avez-vous appris dans cette partie du cours ?
Vous avez centralisé données et logique dans un service que vous avez ensuite injecté dans les components concernés.
Vous avez ajouté un module de routing à votre application, et trois routes fonctionnelles.
Vous avez mis en place deux systèmes pour que vos utilisateurs puissent changer de route : les routerLinks et le Router.
À la fin du quiz qui suit ce chapitre, vous aurez terminé ce cours d'introduction à Angular ! Vous avez déjà appris beaucoup de choses. Mais ce n'est pas fini ! Après le dernier quiz, je vous partagerai comment poursuivre votre apprentissage du framework Angular...