La page Accueil
Maintenant que nous avons une jolie navbar, nous pouvons coder une belle page "Accueil" 🏠
On veut quelque chose qui ressemble à ça.
Création du HomeComponent
Comme pour la génération du NavbarComponant
, tu peux générer un nouveau composant pour la page "Accueil" avec Angular CLI !
app.component.html
via la valeur du selector
.
Attention
N'oublie pas les imports !!
Tu dois avoir home works!
qui s'affiche sur ta page !
Appel au backend
Les données à afficher sur la page viennent du backend que tu as lancé au moment des installations.
Info
Un backend et un frontend communiquent généralement via des appels HTTP.
Tous les appels que tu peux faire à ce backend (codé pour toi) sont définis sur sa documentation
🚀 Notre objectif est donc de récupérer tous les films via un appel HTTP au backend et de les afficher sur notre page
1. Création du modèle
Pour récupérer tous les films nous utilisons cet endpoint qui est un appel GET.
Il retourne une liste d'objets Movie de cette forme :
{
"id": 0,
"title": "string",
"director": "string",
"rate": 0,
"releaseDate": "2024-05-27T14:53:27.038Z",
"synopsis": "string",
"image": "string"
}
Côté front, nous devons créer un objet qui ressemble à ce Movie pour pouvoir récupérer les données au moment de l'appel.
C'est parti :
- Clic-droit sur le dossier
app
et crée un dossier que tu appellesmodels
- Clic-droit sur ce dossier
models
et crée un ficher que tu appellesmovie.ts
- Dans ce fichier, crée l'objet qui représente les films en se basant sur le modèle du backend :
export interface Movie {
id?: number;
title: string;
releaseDate: Date;
director: string;
rate?: number;
synopsis: string;
image?: string;
}
Info
On utilise export pour pouvoir utiliser cet objet dans d'autres fichiers
On fait une interface qui correspond au modèle du backend (avec les mêmes noms de champs et des types adaptés)
2. Création d'un service pour appeler le backend
Nous avons besoin d'un service que nous pourrons appeler dans nos composants pour requêter notre backend.
La commande pour générer un service est très semblable à celle qui nous permet de générer un composant :
Info
Le services/
permet de préciser un dossier dans lequel mettre le service.
Si le dossier n'existe pas, il le crée.
Pour faire des appels HTTP à notre backend, nous avons besoin d'un service fourni par Angular qu'il faut provider de manière globale : le HttpClient
.
Pour ça, ajoute dans la liste des providers
du app.config.ts
: provideHttpClient()
Tu dois donc avoir :
export const appConfig: ApplicationConfig = {
providers: [provideRouter(routes), provideHttpClient()]
};
Maintenant, il faut faire l'appel à notre backend :
- Rends-toi dans le fichier créé
movies.service.ts
- Supprime le
constructor
- Injecte l'
HttpClient
dans la classe en déclarant une variable :private readonly httpClient = inject(HttpClient)
- Déclare l'url de ton backend sur laquelle se trouve les données que tu veux récupérer :
private readonly url = "http://localhost:8080/movies"
- Crée une méthode dans la classe qui fait l'appel GET :
Info
Comme nous récupérons des données via un appel GET, nous utilisons la méthode get
de l'HttpClient
.
Notre appel récupère une liste de Movie
que l'on doit préciser au niveau de la méthode.
Les méthodes de l'HttpClient
nous retournent toujours un Observable
.
Un Observable
est un objet qui permet de gérer des flux de données asynchrones :
on doit subscribe
pour récupérer son contenu.
Bravo, ton appel est créé !! ⭐
3. Appel du service dans le composant
Maintenant que ton appel au backend est accessible depuis la méthode getMovies()
dans un service, tu dois l'appeler dans ton composant.
Pour cela :
- Rends-toi dans le fichier
home.component.ts
- Injecte ton service en créant une variable
private readonly moviesService = inject(MoviesService)
- Crée une variable pour récupérer ta liste de
Movie
:movies$: Observable<Movie[]> = this.moviesService.getMovies()
Info
Comme vu un peu plus haut, on doit subscribe
pour réellement trigger l'appel HTTP et récupérer le contenu d'un observable. On peut le faire de deux façons :
Soit en utilisant le .subscribe()
comme ça :
movies: Movie[] = []
this.moviesService.getMovies.subscribe(moviesFromBackend => this.movies = moviesFromBackend)
| async
dans une directive (@if ou @for)côté HTML :
Si c'est possible, il faut choisir cette façon qui est plus performante.
Dans notre cas, on utilise bien le | async
dans le home.component.html
.
Une fois qu'on a récupéré notre liste de films, on boucle sur la liste avec un @for
et on affiche les films un par un :
@for (movie of movies$ | async; track movie.id) {
<p>{{movie.id}}</p>
<p>{{movie.title}}</p>
<p>{{movie.releaseDate | date:'dd/MM/yyyy'}}</p>
<p>{{movie.director}}</p>
<p>{{movie.rate}}</p>
<p>{{movie.synopsis}}</p>
}
Info
Le track
permet à Angular d'identifier l'item de façon unique dans le DOM pour gagner en performance lors de modification de la liste.
Le pipe | date
te permet de formater ta date selon un format (le backend nous renvoie un format de Date classique et ce n'est pas affichable tel quel).
Tu as la documentation.
⚠️ Attention, il faut penser à importer DatePipe
et AsyncPipe
de @angular/common
.
Tadaaaaam, tes données s'affichent sur ta page Accueil !!! ⭐
4. On rend tout ça joli joli
On est content, on a bien nos données du backend qui s'affichent, mais ce n'est pas très beau...
Rappel
On n'oublie pas : dans Angular, tout est composant !
C'est une bonne pratique, lorsque l'on voit le même objet plusieurs fois, de créer un composant réutilisable de cet objet qui a une seule responsabilité.
On va donc créer un composant qui a la responsabilité d'afficher un film !
Normalement, là, ça devrait faire tilt dans ta tête, un nouveau composant = ng generate component + un petit nom
C'est parti !
Maintenant, on remplace nos balises <p></p>
par notre nouveau composant dans le home.component.html
:
movie
à notre MovieComponent
.
Pour ça, souviens-toi, c'est avec le décorateur @Input()
et le property binding []
Solution
- Dans
movie.component.ts
, on ajoute donc@Input({required: true}) movie!: Movie
- Dans
home.component.html
, on ajoute le property binding[movie]=movie
Jette un oeil, à ton localhost maintenant que ca recompile ! On itère bien sur le MovieComponent
.
On a donc accès à la variable movie
dans le movie.component.html
et on peut faire un truc tout beau !
On te propose d'utiliser les cards de Bootstrap. Tu peux t'inspirer de ce bout de code :
<div class="card shadow m-4" style="width: 18rem; min-height: 55rem">
@if(movie.image) {
<img src="http://localhost:8080/movies/'+movie.id +'/image" class="card-img-top" alt="">
}
<div class="card-body">
<h5 class="card-title">{{movie.title}}</h5>
<p class="card-text">{{movie.synopsis}}</p>
<label class="note">Note: {{movie.rate}}</label>
</div>
</div>
Info
Le @if
nous permet d'afficher l'image uniquement si elle existe bien.
On la récupère ensuite depuis un appel HTTP au backend.
Pour que ce soit tout nickel, tu peux ajouter ce style dans le home.component.scss
:
Et voilaaaaa ton composant home est terminé ! ⭐
🙋♀️ Checkpoint time 🙋