Cours Angular · Module 5: Services et DI
Les services dans Angular - Les guildes d'artisans
Dans cette leçon3
Les services dans Angular sont comme des guildes d'artisans : des unités spécialisées qui fournissent leurs services à tout le royaume. Chaque guilde a sa spécialité : les forgerons forgent les épées, les tailleurs cousent les kimonos.
Qu'est-ce qu'un service ?
Un service est une classe responsable de :
- Logique métier - calculs, validations
- Communication API - récupération/envoi de données
- Gestion d'état - stockage de données entre les composants
- Partage de code - éviter la duplication
Créer un service
1import { Injectable } from '@angular/core';
2
3@Injectable({
4 providedIn: 'root' // Singleton disponible dans toute l'application
5})
6export class KatanaService {
7 private katanas: Katana[] = [];
8
9 getAll(): Katana[] {
10 return [...this.katanas]; // On retourne une copie
11 }
12
13 getById(id: number): Katana | undefined {
14 return this.katanas.find(k => k.id === id);
15 }
16
17 forge(name: string, type: string): Katana {
18 const katana: Katana = {
19 id: Date.now(),
20 name,
21 type,
22 damage: Math.floor(Math.random() * 100) + 50,
23 createdAt: new Date()
24 };
25 this.katanas.push(katana);
26 return katana;
27 }
28
29 destroy(id: number): boolean {
30 const index = this.katanas.findIndex(k => k.id === id);
31 if (index > -1) {
32 this.katanas.splice(index, 1);
33 return true;
34 }
35 return false;
36 }
37}Générer via le CLI
1ng generate service services/katana
2# ou en version courte :
3ng g s services/katanaCode de cette leçon : src/app/app.component.ts
1import { Component, inject } from '@angular/core';
2import { SamuraiService } from './services/samurai.service';
3import { LoggerService } from './services/logger.service';
4
5@Component({
6 selector: 'app-root',
7 standalone: true,
8 template: `
9 <div class="guild-hall">
10 <header>
11 <h1>La guilde des artisans</h1>
12 <p>Module 5 : services et injection de dépendances</p>
13 </header>
14
15 <main>
16 <section class="info-panel">
17 <h2>À propos des services</h2>
18 <p>Les services sont des guildes d’artisans - des spécialistes de tâches précises.</p>
19 <ul>
20 <li>@Injectable() - enregistrement dans la DI</li>
21 <li>providedIn: 'root' - singleton</li>
22 <li>inject() - l’injection moderne</li>
23 </ul>
24 </section>
25
26 <section class="demo-panel">
27 <h2>Liste des samouraïs (depuis le service)</h2>
28 <div class="samurai-list">
29 @for (s of samuraiList; track s.id) {
30 <div class="samurai-card">
31 <strong>{{ s.name }}</strong>
32 <span>Clan : {{ s.clan }}</span>
33 <span>Niveau : {{ s.level }}</span>
34 </div>
35 }
36 </div>
37 <div class="actions">
38 <button (click)="addSamurai()">Ajouter un samouraï</button>
39 <button (click)="showLogs()">Afficher les logs</button>
40 </div>
41 </section>
42
43 <section class="logs-panel" *ngIf="logs.length">
44 <h3>Logs (depuis LoggerService)</h3>
45 <ul>
46 @for (log of logs; track $index) {
47 <li>{{ log }}</li>
48 }
49 </ul>
50 </section>
51 </main>
52 </div>
53 `,
54 styles: [`
55 .guild-hall {
56 font-family: 'Segoe UI', sans-serif;
57 max-width: 900px;
58 margin: 0 auto;
59 padding: 20px;
60 background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%);
61 min-height: 100vh;
62 color: #eee;
63 }
64 header {
65 text-align: center;
66 border-bottom: 2px solid #c9a227;
67 padding-bottom: 20px;
68 }
69 h1, h2, h3 { color: #c9a227; }
70 .info-panel, .demo-panel, .logs-panel {
71 background: rgba(255,255,255,0.05);
72 border: 1px solid #c9a227;
73 border-radius: 8px;
74 padding: 20px;
75 margin: 20px 0;
76 }
77 ul { list-style: none; padding: 0; }
78 li::before { content: "» "; }
79 .samurai-card {
80 background: #16213e;
81 border: 1px solid #333;
82 border-radius: 8px;
83 padding: 15px;
84 margin: 10px 0;
85 display: flex;
86 justify-content: space-between;
87 }
88 .actions {
89 display: flex;
90 gap: 10px;
91 margin-top: 15px;
92 }
93 button {
94 background: #c9a227;
95 color: #1a1a2e;
96 border: none;
97 padding: 10px 20px;
98 border-radius: 4px;
99 cursor: pointer;
100 }
101 button:hover { opacity: 0.9; }
102 .logs-panel ul {
103 background: #0d1117;
104 padding: 15px;
105 border-radius: 4px;
106 font-family: monospace;
107 font-size: 0.9rem;
108 }
109 .logs-panel li::before { content: "› "; color: #4ade80; }
110 `]
111})
112export class AppComponent {
113 private samuraiService = inject(SamuraiService);
114 private logger = inject(LoggerService);
115
116 samuraiList = this.samuraiService.getAll();
117 logs: string[] = [];
118
119 addSamurai() {
120 const newSamurai = {
121 id: Date.now(),
122 name: 'Nouveau guerrier',
123 clan: 'Ronin',
124 level: 1
125 };
126 this.samuraiService.add(newSamurai);
127 this.samuraiList = this.samuraiService.getAll();
128 this.logger.log('Nouveau samouraï ajouté : ' + newSamurai.name);
129 }
130
131 showLogs() {
132 this.logs = this.logger.getLogs();
133 }
134}Tu as repéré une erreur dans cette leçon ?
Teste tes connaissances
Réponds aux questions de cette leçon. Choisis une réponse pour voir tout de suite si elle est correcte.
1. Quel décorateur marque une classe comme service dans Angular ?
2. D'après la leçon, de quoi un Service est-il responsable dans Angular ?
Voici 2 des 3 questions de cette leçon. Réponds aux autres dans le jeu.
Tâches pratiques dans le jeu
- Tri horizontal
Ordonne sur une seule ligne l'import du décorateur Injectable :
- Éditeur de code
Complète SamuraiService pour qu'Angular puisse l'injecter et crée une seule instance partagée pour toute l'application.
- Clique dans l'ordre
Clique dans l'ordre pour construire la commande Angular CLI qui génère un service :