Angular
Debutant
Quiz-Angular-Debutant
Composants-Standalone
Directives-Ngif-Ngfor
Angular-Pipes
Angular-Routing
Questions-Entretien-Angular
Qcm-Angular
Angular-Input-Output
Angular-Services
Cycle-De-Vie-Angular
Angular-17
Front-End
📝
Entretien Angular Débutant — Composants, Pipes et Routing
20 questions sur les fondamentaux d'Angular 17 : composants standalone, @Input/@Output, directives (*ngIf, *ngFor, @if, @for), pipes natifs, services, cycle de vie et routing. Préparez votre entretien Angular.
Banque de révision : les 60 questions corrigées
Voici l'intégralité des 60 questions de « Entretien Angular Débutant — Composants, Pipes et Routing », chacune avec sa bonne réponse et son explication. Le quiz interactif ci-dessus en tire une sélection aléatoire à chaque tentative — utilisez cette liste complète pour réviser.
Explication :
La commande
ng new mon-projet est utilisée pour créer un nouveau projet Angular. Elle fait partie de l'Angular CLI et initialise toute la structure du projet avec les fichiers de configuration nécessaires.
Assurez-vous d'avoir installé Angular CLI globalement avec
npm install -g @angular/cli avant d'utiliser cette commande.
Explication :
Le décorateur
@Component est utilisé pour marquer une classe comme composant Angular. Il prend un objet de configuration avec des propriétés comme selector, template ou templateUrl, et styles ou styleUrls.
Un composant est toujours associé à un template HTML et à des styles CSS.
Explication :
La liaison de propriété (property binding) utilise la syntaxe
[attribut]="expression". Elle permet de lier une propriété du composant vers le DOM, par exemple [src]="imageUrl" ou [disabled]="isDisabled".
La liaison unidirectionnelle du composant vers le template est la plus courante. Pour la liaison inverse (template → composant), utilisez
(event).
Explication :
La liaison bidirectionnelle
[(ngModel)]="property" est un sucre syntaxique combinant la liaison de propriété [ngModel] et la liaison d'événement (ngModelChange). Elle nécessite d'importer FormsModule.
Pour utiliser
ngModel, n'oubliez pas d'ajouter FormsModule aux imports de votre composant autonome ou de votre module.
Explication :
*ngIf est une directive structurelle qui ajoute ou supprime un élément du DOM selon une condition booléenne. Si la condition est false, l'élément et ses enfants sont détruits du DOM.
Utilisez
*ngIf="condition; else autreTemplate" pour afficher un template alternatif. Depuis Angular 17, vous pouvez aussi utiliser la nouvelle syntaxe @if.
Explication :
La directive
*ngFor="let item of items" permet d'itérer sur un tableau. Elle crée un élément DOM pour chaque élément du tableau. On peut aussi obtenir l'index avec *ngFor="let item of items; let i = index".
Pour de meilleures performances, utilisez
trackBy avec *ngFor pour éviter la recréation inutile des éléments DOM.
Explication :
L'injection de dépendances dans Angular se fait automatiquement via le constructeur. Il suffit de déclarer un paramètre avec le type du service dans le constructeur du composant. Le décorateur
@Injectable() marque les services comme injectables.
Angular utilise le système d'injection de dépendances hiérarchique. Un service déclaré dans
providedIn: "root" est un singleton global.
Explication :
Les directives structurelles (
*ngIf, *ngFor, *ngSwitch) modifient la structure du DOM en ajoutant, supprimant ou remplaçant des éléments. Les directives d'attribut (ngClass, ngStyle) modifient l'apparence ou le comportement des éléments existants.
Les directives structurelles sont préfixées par
* dans les templates, tandis que les directives d'attribut s'utilisent entre crochets ou comme attributs normaux.
Explication :
Le décorateur
@Input() permet à un composant enfant de déclarer une propriété qui peut recevoir des données du parent. Le parent utilise la liaison de propriété [nomInput]="valeur" dans le template pour passer la donnée.
Vous pouvez aussi utiliser des setters avec
@Input() pour exécuter du code quand la valeur change.
Explication :
Le composant enfant utilise
@Output() monEvent = new EventEmitter<type>() pour définir un événement. Il émet avec this.monEvent.emit(valeur). Le parent écoute avec (monEvent)="handler($event)" dans le template.
Typez toujours votre EventEmitter pour bénéficier du typage TypeScript. Exemple :
@Output() save = new EventEmitter<User>().
Explication :
Un service est une classe TypeScript décorée avec
@Injectable(). Il permet d'organiser et de partager la logique métier, l'accès aux données, ou les fonctions utilitaires entre plusieurs composants.
Les services favorisent la réutilisabilité et la séparation des préoccupations (single responsibility principle).
Explication :
Les hooks de cycle de vie principaux sont :
constructor() (création de la classe), ngOnChanges() (changement des @Input), ngOnInit() (initialisation), ngDoCheck(), ngAfterContentInit(), ngAfterContentChecked(), ngAfterViewInit(), ngAfterViewChecked(), et ngOnDestroy() (nettoyage).
Placez la logique d'initialisation dans
ngOnInit(), pas dans le constructeur. Le constructeur doit uniquement initialiser l'injection de dépendances.
Explication :
Le pipe
async souscrit automatiquement à un Observable ou une Promise dans le template. Il retourne la dernière valeur émise et gère automatiquement la désinscription quand le composant est détruit.
Utilisez
| async pour éviter les fuites de mémoire, car vous n'avez pas à gérer manuellement la désinscription des Observables.
Explication :
Un composant standalone est créé en définissant
standalone: true dans le décorateur @Component. La commande ng generate component mon-comp --standalone le fait automatiquement. Les composants standalone n'ont pas besoin d'être déclarés dans un NgModule.
Depuis Angular 17, les composants standalone sont la recommandation officielle. Les applications créées avec
ng new les utilisent par défaut.
Explication :
Angular 17 a introduit une nouvelle syntaxe de contrôle de flux basée sur les blocs :
@if, @else if, @else, @for avec @empty, et @switch avec @case et @default. Ces blocs sont plus performants que les directives structurelles traditionnelles.
La nouvelle syntaxe
@for nécessite un track obligatoire pour optimiser le rendu, contrairement à *ngFor où trackBy était optionnel.
Explication :
Deux méthodes existent : l'injection traditionnelle via le constructeur
constructor(private service: MonService) {}, et la nouvelle fonction inject() : private service = inject(MonService). Cette dernière permet l'injection hors des constructeurs (dans les fonctions, les services, etc.).
La fonction
inject() est particulièrement utile dans les fonctions utilitaires ou les guards où vous n'avez pas de constructeur.
Explication :
Le Change Detection est le mécanisme qui permet à Angular de mettre à jour automatiquement la vue quand l'état du composant change. Il compare les valeurs précédentes et actuelles pour déterminer ce qui doit être mis à jour dans le DOM.
Vous pouvez optimiser les performances avec
ChangeDetectionStrategy.OnPush pour limiter les vérifications aux cas où les @Input() changent ou des événements se produisent.
Explication :
La directive
<router-outlet></router-outlet> est le point d'entrée où le routeur Angular affiche le composant correspondant à la route active. C'est un placeholder qui sera remplacé par le contenu du composant routé.
Vous pouvez avoir plusieurs
router-outlet nommés pour le routage imbriqué : <router-outlet name="aux"></router-outlet>.
Explication :
Le service
Router fournit la méthode navigate() pour naviguer programmatiquement : this.router.navigate(["/chemin", id]) ou this.router.navigateByUrl("/chemin").
Utilisez
navigate(["/chemin"], { queryParams: { page: 1 } }) pour passer des paramètres de query string.
Explication :
Les guards (CanActivate, CanDeactivate, Resolve, CanLoad, CanMatch) sont des fonctions ou services qui contrôlent si une route peut être activée, désactivée, ou chargée. Ils permettent l'authentification, l'autorisation, ou le chargement de données avant l'activation.
Depuis Angular 15+, les guards peuvent être des fonctions simples au lieu de classes, ce qui les rend plus légers et plus faciles à tester.
Explication :
Le service
ActivatedRoute fournit params et paramMap comme Observables. On y souscrit pour obtenir les paramètres : this.route.params.subscribe(params => this.id = params["id"]).
Utilisez
this.route.snapshot.paramMap.get("id") si vous êtes sûr que le composant ne sera pas réutilisé avec des paramètres différents.
Explication :
ng serve compile l'application en mémoire, démarre un serveur de développement, et surveille les changements pour recharger automatiquement (live reload). ng build génère les fichiers de sortie dans le dossier dist/ sans serveur.
Utilisez
ng build --prod (ou --configuration production) pour optimiser l'application pour la production (minification, tree-shaking, AOT).
Explication :
Le fichier
angular.json est le fichier de configuration de l'Angular CLI. Il définit les différentes configurations de build, serve, test, les assets, les styles globaux, les polyfills, et les options de compilation.
Vous pouvez avoir plusieurs configurations dans
angular.json (development, production, staging) et les utiliser avec --configuration.
Explication :
La commande
ng generate pipe mon-pipe crée automatiquement un pipe personnalisé. Le fichier généré contient une classe décorée avec @Pipe({ name: "monPipe" }) qui implémente l'interface PipeTransform avec la méthode transform(value, ...args).
Les pipes personnalisés sont utiles pour la transformation réutilisable de données dans les templates (formatage, filtrage, calculs).
Explication :
Le
constructor est appelé en premier lors de l'instanciation du composant, avant que les propriétés @Input() soient initialisées. ngOnInit est appelé après que le composant ait initialisé ses @Input() et est le bon endroit pour la logique d'initialisation dépendante des entrées.
Placez toujours la logique qui dépend des
@Input() dans ngOnInit(), jamais dans le constructeur.
Explication :
Le décorateur
@ViewChild permet d'accéder à un élément DOM, une directive ou un composant enfant depuis la classe parent. Exemple : @ViewChild(MonComponent) enfant!: MonComponent; pour appeler des méthodes sur l'enfant.
Accédez à la référence après
ngAfterViewInit(), car c'est le premier hook où la vue est initialisée.
Explication :
providedIn: "root" dans le décorateur @Injectable() signifie que le service est enregistré dans l'injecteur racine (root injector). Cela crée un singleton global accessible à toute l'application et optimise le tree-shaking.
C'est la façon recommandée de fournir des services depuis Angular 6+. Évitez d'ajouter manuellement les services dans
providers: [] sauf besoin spécifique.
Explication :
La directive
ngClass permet d'appliquer des classes CSS conditionnellement : [ngClass]="{"active": isActive, "disabled": isDisabled}" ou avec un tableau [ngClass]="["class1", "class2"]" ou une chaîne.
Vous pouvez aussi utiliser
[class.active]="isActive" pour une seule classe, ou la nouvelle syntaxe @if avec l'attribut class.
Explication :
Le lazy loading (chargement paresseux) permet de charger des parties de l'application (routes, composants) uniquement lorsque l'utilisateur y accède. Cela réduit la taille du bundle initial et améliore les performances. En Angular 17+, on utilise
loadComponent: () => import("./mon.component") dans les routes.
Combine le lazy loading avec les composants standalone pour des bundles encore plus optimisés.
Explication :
Angular 17 a introduit les Deferrable Views (blocs
@defer) qui permettent de différer le chargement de parties du template avec différents déclencheurs (viewport, interaction, idle, timer). Combiné avec le rendu hybride, cela offre des performances améliorées pour l'expérience utilisateur.
Utilisez
@defer (on viewport) { <mon-composant-lourd /> } @placeholder { <div>Chargement...</div> } pour charger un composant uniquement quand il devient visible.
Explication :
L'interpolation dans Angular utilise la syntaxe
{{ expression }} (double accolades). Angular évalue l'expression et insère le résultat dans le HTML. On peut y mettre des variables, des appels de méthode ou des expressions simples.
L'interpolation est équivalente à un
[textContent]="expression". Elle échappe automatiquement le HTML pour prévenir les attaques XSS.
Explication :
La liaison d'événement (event binding) dans Angular utilise la syntaxe
(événement)="handler()". Les parenthèses indiquent un événement. On peut écouter n'importe quel événement DOM : (click), (keyup), (submit), etc.
Pour accéder à l'objet événement natif, utilisez
$event : (click)="handleClick($event)".
Explication :
Un NgModule est une classe décorée avec
@NgModule() qui organise le code en blocs cohérents. Il déclare des composants (declarations), importe d'autres modules (imports), exporte des éléments (exports) et fournit des services (providers). Depuis Angular 17, les composants standalone sont préférés.
Dans les nouvelles applications Angular 17+, vous utilisez des composants standalone au lieu des NgModules. Les NgModules restent supportés pour la compatibilité ascendante.
Explication :
Une variable de template locale se déclare avec
#nomVariable sur un élément HTML ou un composant. Elle crée une référence locale utilisable dans le template. Exemple : <input #nomInput> puis <button (click)="log(nomInput.value)">.
Les variables de template sont locales au template et ne sont pas accessibles directement dans la classe du composant sans
@ViewChild.
Explication :
Le pipe
date d'Angular formate un objet Date ou un timestamp. La syntaxe est date | date:"format". Les formats courants : "short", "medium", "long", "dd/MM/yyyy", "HH:mm".
Le pipe
date d'Angular gère aussi l'internationalisation. Utilisez {{ date | date:"dd/MM/yyyy":"":"fr" }} pour forcer la locale française.
Explication :
La liaison de style (style binding) utilise la syntaxe
[style.propriété]="expression". On peut aussi utiliser la directive [ngStyle] pour plusieurs styles : [ngStyle]="{"color": isRed ? "red" : "blue", "fontSize": size + "px"}".
Pour les styles avec tiret (ex: font-size), Angular supporte les deux notations :
[style.font-size] ou [style.fontSize] (camelCase).
Explication :
<ng-container> est un élément de regroupement logique qui n'est pas rendu dans le DOM final. Il est utile pour appliquer plusieurs directives structurelles sans ajouter d'élément HTML inutile, ou pour grouper des éléments frères.
Cas d'usage courant :
<ng-container *ngIf="condition"><li *ngFor="let item of items">...</li></ng-container> pour combiner *ngIf et *ngFor sans balise intermédiaire.
Explication :
Un formulaire réactif se crée en construisant un
FormGroup contenant des FormControl. Exemple : form = new FormGroup({ name: new FormControl(""), email: new FormControl("") }). Ensuite, on lie le formulaire dans le template avec [formGroup]="form".
Utilisez
FormBuilder (service injectble) pour simplifier la création : form = this.fb.group({ name: [""], email: [""] }).
Explication :
Le pipe
uppercase transforme une chaîne en majuscules. Angular fournit aussi lowercase pour les minuscules et titlecase pour mettre la première lettre de chaque mot en majuscule.
Chaîner les pipes :
{{ texte | trim | lowercase }} — les pipes s'appliquent de gauche à droite. Note : trim n'existe pas en natif, c'est un exemple de pipe personnalisé.
Explication :
Les paramètres de route se définissent avec
:nomDuParamètre dans le chemin. Exemple : { path: "users/:id", component: UserComponent }. Accès dans le composant via ActivatedRoute.snapshot.paramMap.get("id").
On peut avoir plusieurs paramètres :
{ path: "users/:userId/posts/:postId" }. Pour des paramètres optionnels, utilisez les query params : /users?page=1.
Explication :
Le pipe
json convertit n'importe quelle valeur JavaScript en sa représentation JSON lisible avec JSON.stringify(). Il est principalement utilisé pour déboguer : <pre>{{ monObjet | json }}</pre>.
Très pratique pendant le développement pour visualiser la structure d'un objet directement dans le template, mais à retirer avant la mise en production.
Explication :
La directive
routerLink permet de créer des liens de navigation Angular sans rechargement de page. On peut aussi passer un tableau pour construire le chemin : [routerLink]="["/users", userId]".
Ajoutez
routerLinkActive="active" pour appliquer automatiquement une classe CSS quand la route correspondante est active.
Explication :
Pour accéder à l'élément DOM sur lequel une directive est appliquée, on injecte
ElementRef dans le constructeur de la directive. this.el.nativeElement donne accès à l'élément DOM natif.
Préférez
@HostBinding et @HostListener pour manipuler les propriétés et écouter les événements de l'élément hôte sans manipuler directement le DOM natif.
Explication :
Le service
HttpClient est injecté dans le composant et ses méthodes retournent des Observables. On appelle this.http.get<T>("/api/data") et on souscrit avec .subscribe(). Ne pas oublier provideHttpClient() dans app.config.ts.
Il est recommandé de placer les appels HTTP dans des services, pas directement dans les composants, pour une meilleure architecture et testabilité.
Explication :
ngOnDestroy est appelé juste avant la destruction du composant. C'est le bon endroit pour se désinscrire des Observables, effacer les intervalles ou libérer toute ressource qui pourrait causer des fuites mémoire.
Implémentez l'interface
OnDestroy pour signaler clairement l'intention : export class MonComposant implements OnInit, OnDestroy.
Explication :
On peut passer des données via les paramètres de route (
/users/42), les query params (/users?page=2&sort=name), ou les fragments (/users#section). L'enfant les récupère via ActivatedRoute.
Pour naviguer avec des query params :
this.router.navigate(["/users"], { queryParams: { page: 1 } }). Pour les préserver lors de la navigation, utilisez queryParamsHandling: "merge".
Explication :
Dans les templates Angular,
| est l'opérateur pipe. Il passe la valeur à gauche comme argument à la fonction pipe à droite. Les pipes peuvent être chaînés : {{ valeur | pipe1 | pipe2 }}.
Les pipes peuvent accepter des arguments séparés par
:. Exemple : {{ montant | currency:"EUR":"symbol":"1.2-2" }}.
Explication :
La liaison
[innerHTML] permet d'injecter du HTML dans un élément. Angular sanitize automatiquement le contenu pour enlever les éléments dangereux (scripts, etc.). Pour insérer du HTML en toute confiance, utilisez DomSanitizer.bypassSecurityTrustHtml().
Soyez prudent avec
[innerHTML] : n'injectez jamais du HTML venant directement de l'utilisateur sans sanitization pour éviter les attaques XSS.
Explication :
@Input() permet au parent de passer une valeur à l'enfant (flux descendant). @Output() combiné avec un EventEmitter permet à l'enfant de notifier le parent d'un événement (flux montant). Ensemble, ils permettent la communication parent-enfant bidirectionnelle.
Pensez à
@Input()/@Output() comme des portes : Input est la porte d'entrée des données, Output est la porte de sortie des événements.
Explication :
[ngSwitch] est une directive d'attribut placée sur le conteneur. Les cas sont définis avec *ngSwitchCase="valeur" et le défaut avec *ngSwitchDefault. Depuis Angular 17, vous pouvez utiliser la nouvelle syntaxe @switch et @case.
Nouvelle syntaxe Angular 17 :
@switch (valeur) { @case ("A") { Case A } @default { Default } }.
Explication :
<ng-content> permet à un composant d'afficher le contenu que le parent lui passe entre ses balises. Exemple : dans un composant <app-card>, on place <ng-content></ng-content> dans son template, et le parent peut écrire <app-card><p>Mon texte</p></app-card>.
La projection sélective se fait avec
<ng-content select=".header"></ng-content> pour projeter uniquement les éléments avec la classe "header".
Explication :
ng generate service mon-service (abrégé ng g s mon-service) génère automatiquement un fichier mon-service.service.ts et son fichier de test mon-service.service.spec.ts.
Pour générer dans un sous-dossier :
ng g s services/auth → créera src/app/services/auth.service.ts.
Explication :
Les fichiers
environment.ts (dev) et environment.prod.ts (prod) permettent de définir des constantes qui varient selon l'environnement : URLs d'API, clés, flags de debug. Angular CLI les remplace automatiquement au build selon la configuration.
Accès dans le code :
import { environment } from "../environments/environment"; puis environment.apiUrl.
Explication :
Les arguments d'un pipe se passent avec le caractère
: après le nom du pipe. Pour plusieurs arguments : {{ valeur | pipe:arg1:arg2 }}. Exemple : {{ montant | currency:"EUR":"symbol" }}.
Le premier argument après
: est le deuxième paramètre de la méthode transform(value, arg1, arg2) du pipe.
Explication :
@HostListener("eventName") permet d'écouter des événements sur l'élément hôte directement depuis la classe du composant ou de la directive. Exemple : @HostListener("click", ["$event"]) onClick(event) { ... }.
On peut aussi écouter des événements du document ou de la fenêtre :
@HostListener("window:resize", ["$event"]).
Explication :
Les validateurs s'ajoutent en deuxième argument du
FormControl. Un seul validateur : new FormControl("", Validators.required). Plusieurs validateurs : new FormControl("", [Validators.required, Validators.minLength(3)]).
Pour afficher les erreurs :
form.get("nom").errors?.["required"]. L'état de validité est accessible via form.get("nom").valid et .invalid.
Explication :
ng generate guard nom-du-guard (ou ng g guard nom-du-guard) génère un guard. L'Angular CLI demande quel type de guard créer (CanActivate, CanDeactivate, etc.).
Pour créer un guard CanActivate directement :
ng g guard auth --implements CanActivate.
Explication :
Par défaut, les pipes Angular sont "purs" : ils ne recalculent le résultat que quand la valeur d'entrée change de référence (nouveaux objets/arrays). Un pipe "impur" (
pure: false) est réévalué à chaque cycle de détection de changement, ce qui est plus flexible mais moins performant.
Le pipe
async est un exemple de pipe impur car il souscrit à des Observables qui peuvent émettre à n'importe quel moment.
Explication :
La propriété
redirectTo dans la configuration d'une route effectue une redirection. La clé pathMatch: "full" est obligatoire pour la route vide "" pour éviter qu'elle ne capture toutes les URLs.
Pour une page 404, ajoutez à la fin du tableau de routes :
{ path: "**", component: NotFoundComponent }. L'ordre des routes est important : la route wildcard doit toujours être en dernier.
Explication :
Le pipe
currency formate un nombre comme une devise. Arguments : code devise (ex: "EUR", "USD"), affichage ("symbol" montre €, "code" montre EUR), format numérique. Exemple : {{ 1234.5 | currency:"EUR":"symbol":"1.2-2" }} donne "€1 234,50" selon la locale.
Pour personnaliser la locale : ajoutez
LOCALE_ID dans les providers de votre application. N'oubliez pas d'enregistrer la locale avec registerLocaleData(localeFr).