Angular in 10 steps - 3 of 10

03 - I componenti: i mattoncini di Angular
Benvenuto nel terzo capitolo! L'ambiente di sviluppo è pronto, quindi da qui in poi si scrive codice. E si parte dal cuore di Angular: i componenti.
Nel primo capitolo ti ho detto che in Angular "tutto ruota attorno ai componenti". Ora ti mostro cosa significa in pratica: alla fine di questo capitolo saprai crearne uno, capire quando ha senso farlo e iniziare a ragionare "a componenti" quando strutturi un'applicazione.
🧩 Cos'è un componente
Un componente è un pezzo riutilizzabile di interfaccia che tiene insieme tre cose:
- HTML: la struttura
- CSS: lo stile
- TypeScript: la logica
L'analogia classica è quella dei LEGO e, per una volta, è anche quella giusta. Ogni mattoncino ha una forma e un colore (HTML e CSS) e alcuni hanno funzionalità speciali (TypeScript). I mattoncini si combinano per costruire cose più grandi, lo stesso pezzo si riusa in punti diversi e, se un tipo di mattoncino va modificato, lo cambi una volta sola e il cambiamento arriva ovunque.
Apri un sito qualsiasi e li vedi subito: l'header con logo e menu, la card prodotto con immagine, prezzo e bottone, il form di contatto, il footer. Ogni elemento che si ripete, o che ha una logica tutta sua, è un buon candidato a diventare componente.
Perché conviene
Te lo riassumo con i motivi che pesano davvero nel lavoro di tutti i giorni:
- Riutilizzo: scrivi un bottone una volta e lo usi in cinquanta posti
- Leggibilità: tanti file piccoli e focalizzati invece di un HTML da 500 righe
- Manutenzione: un bug nella card si sistema in un punto solo
- Lavoro in team: ognuno sul suo componente, senza pestarsi i piedi
- Test: ogni pezzo si prova in isolamento, senza tirare su tutta l'app
Quando l'app cresce, aggiungere una funzionalità diventa spesso questione di combinare componenti che hai già.
🔧 Com'è fatto un componente in Angular
In Angular un componente è una classe TypeScript decorata con @Component:
1import { Component } from '@angular/core';
2
3@Component({
4 selector: 'app-saluto', // il tag da usare nell'HTML
5 template: `<h1>{{ titolo }}</h1>`, // il template
6 styles: [`h1 { color: rebeccapurple; }`]
7})
8export class SalutoComponent {
9 titolo = 'Il mio primo componente';
10}I pezzi sono tre:
- Il decorator
@Component, che dice ad Angular "questa classe è un componente" e ne definisce selector, template e stili - La classe, con le proprietà (i dati) e i metodi (le azioni)
- Il template, cioè HTML normale più la sintassi di binding di Angular
Una parola sugli standalone component
Se hai incrociato Angular qualche anno fa, ricorderai che ogni componente andava
dichiarato dentro un NgModule, con relativo boilerplate. Dalla versione 14 sono
arrivati gli standalone component, componenti indipendenti che importano
direttamente ciò che gli serve. E dalla versione 19 gli standalone sono il
comportamento predefinito: non serve nemmeno più scrivere standalone: true.
In questa guida usiamo Angular moderno, quindi standalone e basta. Gli NgModule li nomineremo solo quando serviranno a capire codice esistente.
Se un tutorial ti fa dichiarare il componente dentro un NgModule, o insiste su
standalone: true, è scritto per una versione vecchia di Angular. Non è sbagliato, ma non è più il modo consigliato di lavorare.
🛠 Creiamo il primo componente
Riprendiamo il progetto del capitolo precedente:
cd il-mio-primo-progetto
code .E generiamo un componente con la CLI (la shortcut è ng g c benvenuto):
ng generate component benvenutoLa CLI crea quattro file:
1src/app/benvenuto/
2├── benvenuto.component.ts # la logica
3├── benvenuto.component.html # il template
4├── benvenuto.component.css # gli stili
5└── benvenuto.component.spec.ts # i testIl file TypeScript generato è già uno standalone component, pronto all'uso:
1import { Component } from '@angular/core';
2
3@Component({
4 selector: 'app-benvenuto',
5 imports: [],
6 templateUrl: './benvenuto.component.html',
7 styleUrl: './benvenuto.component.css'
8})
9export class BenvenutoComponent {
10
11}Adesso personalizziamolo. Aggiungiamo un paio di proprietà e due metodi:
1import { Component } from '@angular/core';
2
3@Component({
4 selector: 'app-benvenuto',
5 imports: [],
6 templateUrl: './benvenuto.component.html',
7 styleUrl: './benvenuto.component.css'
8})
9export class BenvenutoComponent {
10 nome = 'sviluppatore';
11 messaggio = 'Benvenuto nel mondo di Angular!';
12 numeroVisite = 0;
13
14 incrementaVisite() {
15 this.numeroVisite++;
16 }
17
18 cambiaNome(nuovoNome: string) {
19 this.nome = nuovoNome;
20 }
21}Poi il template, in benvenuto.component.html:
1<div class="card-benvenuto">
2 <h2>{{ messaggio }}</h2>
3 <p>Ciao <strong>{{ nome }}</strong>!</p>
4 <p>Hai cliccato {{ numeroVisite }} volte.</p>
5
6 <button (click)="incrementaVisite()">Incrementa</button>
7 <button (click)="cambiaNome('Angular developer')">Cambia nome</button>
8</div>E un minimo di stile in benvenuto.component.css:
1.card-benvenuto {
2 max-width: 400px;
3 margin: 2rem auto;
4 padding: 2rem;
5 border: 1px solid #ddd;
6 border-radius: 12px;
7 text-align: center;
8}
9
10.card-benvenuto button {
11 margin: 0.5rem 0.25rem 0;
12 padding: 0.5rem 1rem;
13 cursor: pointer;
14}Il componente esiste, ma nessuno lo sta usando. Apri src/app/app.component.html
e sostituisci tutto il contenuto con:
1<div class="container">
2 <h1>La mia app Angular</h1>
3 <app-benvenuto></app-benvenuto>
4</div>Ultimo passaggio, quello che all'inizio si dimentica sempre: il componente va
importato da chi lo usa. In src/app/app.component.ts:
1import { Component } from '@angular/core';
2import { BenvenutoComponent } from './benvenuto/benvenuto.component';
3
4@Component({
5 selector: 'app-root',
6 imports: [BenvenutoComponent], // senza questo, il tag non viene riconosciuto
7 templateUrl: './app.component.html',
8 styleUrl: './app.component.css'
9})
10export class AppComponent {
11 title = 'il-mio-primo-progetto';
12}Avvia il server con ng serve, vai su http://localhost:4200 e gioca con i due
bottoni: stai già usando proprietà, eventi e interpolazione senza aver scritto una
riga di codice "di collegamento". Questo è il punto di Angular.
🔄 Il data binding, in breve
Nel componente appena scritto abbiamo già usato due tipi di data binding, il meccanismo con cui template e classe si parlano. In tutto sono quattro:
Interpolation {{ }}: mostra il valore di una proprietà nel template
<h2>{{ messaggio }}</h2>Event binding (evento): esegue un metodo quando succede qualcosa
<button (click)="incrementaVisite()">Clicca</button>Property binding [proprieta]: imposta una proprietà HTML da una proprietà della classe
<img [src]="urlImmagine" [alt]="descrizione">Two-way binding [(ngModel)]: tiene sincronizzati un input e una proprietà, nelle due direzioni
<input [(ngModel)]="nome" placeholder="Il tuo nome">Per ora ti basta riconoscerli. Al data binding, e ai signals che ti avevo anticipato nel primo capitolo, dedicheremo un capitolo intero più avanti.
Il ciclo di vita di un componente
Ogni componente vive una vita: nasce, reagisce ai cambiamenti e prima o poi viene distrutto. Angular ti permette di agganciarti a questi momenti con i lifecycle hooks, metodi speciali che vengono chiamati automaticamente:
ngOnInit()viene eseguito una volta sola, all'inizializzazione: perfetto per caricare datingOnChanges()scatta quando cambiano gli input del componentengOnDestroy()viene chiamato prima della rimozione: il posto giusto per pulire timer e sottoscrizioni
1import { Component, OnInit, OnDestroy } from '@angular/core';
2
3@Component({ /* ... */ })
4export class MyComponent implements OnInit, OnDestroy {
5 ngOnInit() {
6 console.log('componente inizializzato');
7 }
8
9 ngOnDestroy() {
10 console.log('componente distrutto');
11 }
12}Non serve impararli tutti adesso. ngOnInit e ngOnDestroy coprono la maggior
parte dei casi reali, gli altri li incontreremo strada facendo.
Qualche buona abitudine
Tre regole che mi hanno risparmiato parecchi mal di testa nei progetti veri:
- Nomi coerenti: file
user-card.component.ts, classeUserCardComponent, selectorapp-user-card. La CLI li genera già così, non combatterla - Componenti piccoli: se il template supera le 100 righe, probabilmente dentro ci vivono due o tre componenti che chiedono di uscire
- Una responsabilità sola:
UserCardComponentmostra un utente. Se lo stesso componente mostra la lista, il dettaglio, il form e la validazione, qualcosa è andato storto
I comandi CLI che uso davvero
Oltre a ng g c nome, questi flag tornano utili spesso:
1# in una sottocartella
2ng g c features/user-profile
3
4# senza file di test
5ng g c mio-comp --skip-tests
6
7# template e stili inline, per componenti minuscoli
8ng g c mio-comp --inline-template --inline-style
9
10# anteprima di cosa verrebbe creato, senza creare nulla
11ng g c mio-comp --dry-runIl --dry-run in particolare vale oro: prima di generare qualcosa in un progetto
grosso, controlli dove andranno a finire i file.
Dove siamo arrivati
Ora sai cos'è un componente, perché è l'unità di misura di qualsiasi app Angular, come crearne uno con la CLI e come collegare dati ed eventi al template. Non è poco: è il modo di ragionare che userai per tutto il resto della guida.
Nel prossimo capitolo entra in scena il Router: trasformeremo i nostri componenti in vere e proprie pagine navigabili, come si aspetta chiunque apra un'applicazione web.