È uscito il Corso Java Completo
Torna al blog

Cos'è Angular e quando ha senso

Cos'è Angular e come funziona: componenti e standalone, iniezione delle dipendenze, RxJS e Signals, Angular CLI e quando conviene davvero usarlo.

Edoardo Midali

Edoardo Midali

Developer · Content Creator

10 min di lettura

Apri un progetto Angular per la prima volta e trovi decoratori, moduli, classi con cose iniettate nel costruttore e file che finiscono in .service.ts. La reazione normale è "qui c'è troppa roba per fare una lista di prodotti". In questo articolo trovi cosa sono davvero quei pezzi, cos'è l'iniezione delle dipendenze spiegata senza giri di parole, cosa sono gli Observable e quando Angular è invece una zavorra.

Cos'è

Angular è un framework completo per applicazioni web: ti dà già decisi componenti, routing, chiamate HTTP, moduli, test e struttura del progetto, e in cambio ti chiede di fare le cose a modo suo.

La parola importante è "completo". La seconda, non scritta ma altrettanto vera, è "opinionato".

Completo e opinionato: cosa comporta

React è una libreria: si occupa dell'interfaccia e lascia a te il resto da assemblare. Angular è l'opposto: quando lo installi hai già router, client HTTP, strumenti di test, struttura delle cartelle e il modo giusto di organizzare la logica.

Il novanta per cento delle decisioni architetturali le hai già prese, e le ha prese qualcun altro per te.

Detta così sembra una perdita, e invece è il motivo per cui lo si sceglie: due progetti Angular scritti da team diversi si assomigliano molto. Chi apre un repository sconosciuto trova la stessa struttura, gli stessi nomi di file, lo stesso modo di chiamare un'API. Su un progetto che vive otto anni e passa per quindici persone, quell'uniformità vale più della libertà.

La differenza generale tra i due approcci sta in cos'è un framework e cos'è una libreria.

TypeScript non è opzionale

In React e Vue puoi usare TypeScript se vuoi. In Angular è la lingua del framework: i decoratori, l'iniezione delle dipendenze, gli strumenti dell'editor presuppongono i tipi.

Non è un capriccio: il grosso di quello che Angular fa per te — capire cosa iniettare, controllare i template, generare codice — funziona perché i tipi ci sono.

Conseguenza pratica: se non conosci TypeScript, imparalo prima, non insieme. Capire gli Observable mentre litighi con interfacce e generici è il modo più efficiente per convincersi che Angular sia incomprensibile, quando il problema è un altro.

Componenti, moduli e standalone

Il componente Angular è una classe con un decoratore sopra.

import { Component } from "@angular/core";

@Component({
  selector: "app-saluto",
  standalone: true,
  template: `<h1>Ciao, {{ nome }}</h1>`,
})
export class SalutoComponent {
  nome = "Edoardo";
}

Il decoratore @Component è metadati: dice ad Angular con quale tag si usa il componente e qual è il suo template. La classe sotto contiene dati e logica.

La parte che confonde storicamente sono gli NgModule. Per anni ogni componente andava dichiarato dentro un modulo — un file .module.ts che elencava cosa conteneva, importava ed esportava — perché Angular sapesse quali pezzi esistono e come si vedono tra loro.

Era burocrazia pura: aggiungevi un componente e dovevi ricordarti di registrarlo altrove, altrimenti errore. Chi iniziava passava metà del tempo a capire perché un componente "non esisteva".

Gli standalone component eliminano quel passaggio. Il componente dichiara da sé cosa gli serve:

import { Component } from "@angular/core";
import { CommonModule } from "@angular/common";
import { SalutoComponent } from "./saluto.component";

@Component({
  selector: "app-pagina",
  standalone: true,
  imports: [CommonModule, SalutoComponent],
  template: `
    <app-saluto />
    <ul>
      <li *ngFor="let p of prodotti">{{ p }}</li>
    </ul>
  `,
})
export class PaginaComponent {
  prodotti = ["Tastiera", "Monitor", "Mouse"];
}

Le dipendenze stanno dove le usi, non in un file separato. Su un progetto nuovo oggi si parte standalone, e i moduli li incontri solo nel codice esistente. Se leggi una guida che inizia con NgModule, controlla la data.

L'iniezione delle dipendenze

È il concetto che spaventa di più e in realtà è semplice. Il nome suona accademico, il problema che risolve è banale.

Immagina un componente che deve chiamare un'API. La versione ingenua è che il componente si costruisca da sé quello che gli serve:

export class ProdottiComponent {
  private servizio = new ProdottiService(); // se lo crea da solo
}

Funziona, e ha tre problemi. Se dieci componenti fanno così esistono dieci copie dello stesso servizio, e se quel servizio tiene una cache o lo stato dell'utente hai dieci verità diverse. Nei test non puoi sostituirlo con una versione finta, perché è cablato dentro. E se domani il servizio ha bisogno di un parametro, tocchi dieci file.

L'iniezione delle dipendenze capovolge la faccenda: il componente dichiara cosa gli serve e qualcun altro glielo fornisce.

import { Injectable, inject } from "@angular/core";
import { HttpClient } from "@angular/common/http";

@Injectable({ providedIn: "root" })
export class ProdottiService {
  private http = inject(HttpClient);

  elenco() {
    return this.http.get<Prodotto[]>("/api/prodotti");
  }
}
export class ProdottiComponent {
  private prodotti = inject(ProdottiService); // lo chiede, non lo crea
}

Quel providedIn: "root" dice ad Angular di tenerne una sola istanza per tutta l'applicazione: chiunque la chieda riceve la stessa. È qui che il concetto smette di essere astratto — stato dell'utente collegato, cache dei dati, configurazione dell'ambiente devono esistere in copia unica, e l'iniezione te lo garantisce senza variabili globali inventate.

Nei test sostituisci l'oggetto vero con uno finto in una riga, senza toccare il componente: è il motivo per cui in Angular i test sono meno faticosi da scrivere che altrove.

In sostanza: non costruisci le cose, le chiedi. Il resto è dettaglio di configurazione.

RxJS e gli Observable: il vero scoglio

Diciamolo subito: è questo il pezzo su cui la gente si arena, non i componenti e non l'iniezione. E in buona parte è colpa di come viene spiegato.

Il concetto di base è uno solo. Una Promise è un valore singolo che arriva nel futuro: la chiamata parte, prima o poi risponde, finito. Un Observable è un flusso di valori nel tempo: può emetterne zero, uno o infiniti, e tu decidi cosa fare a ogni emissione.

Guarda dove serve davvero — un campo di ricerca che interroga il server mentre l'utente scrive:

import { Component, inject } from "@angular/core";
import { FormControl, ReactiveFormsModule } from "@angular/forms";
import { debounceTime, distinctUntilChanged, switchMap } from "rxjs/operators";

@Component({
  selector: "app-ricerca",
  standalone: true,
  imports: [ReactiveFormsModule],
  template: `<input [formControl]="cerca" />`,
})
export class RicercaComponent {
  private servizio = inject(ProdottiService);
  cerca = new FormControl("");

  risultati$ = this.cerca.valueChanges.pipe(
    debounceTime(300),
    distinctUntilChanged(),
    switchMap((testo) => this.servizio.cerca(testo ?? ""))
  );
}

Quattro righe che, scritte a mano, sono un pomeriggio di lavoro e almeno due bug. debounceTime aspetta che l'utente smetta di digitare, distinctUntilChanged evita di richiedere due volte lo stesso testo, switchMap annulla la richiesta precedente quando ne parte una nuova — il bug classico delle ricerche fatte a mano, dove una risposta lenta arriva dopo una veloce e sovrascrive i risultati giusti.

Questo è RxJS quando ha senso: eventi nel tempo da coordinare. Il problema è che per anni Angular lo ha usato anche per mostrare un numero che cambia, e lì era un cannone per una zanzara.

I Signals stanno semplificando molto

Le versioni recenti di Angular hanno introdotto i Signals, che sono valori reattivi semplici, molto simili a quelli di Vue.

import { Component, signal, computed } from "@angular/core";

@Component({
  selector: "app-carrello",
  standalone: true,
  template: `
    <p>Totale: {{ totale() }} €</p>
    <button (click)="aggiungi()">Aggiungi</button>
  `,
})
export class CarrelloComponent {
  quantita = signal(1);
  prezzo = signal(20);
  totale = computed(() => this.quantita() * this.prezzo());

  aggiungi() {
    this.quantita.update((q) => q + 1);
  }
}

Niente pipe, niente operatori, niente sottoscrizioni da chiudere. La divisione che si sta assestando è: Signals per lo stato dell'interfaccia, RxJS per i flussi di eventi complessi — ricerche, WebSocket, sequenze di chiamate.

Il risultato per chi inizia oggi è che puoi essere produttivo in Angular sapendo pochissimo RxJS, e impararlo quando serve. Fino a un paio d'anni fa non era vero, ed è il motivo per cui la reputazione di Angular è più dura della realtà attuale.

Angular CLI

In React lo strumento a riga di comando è una cosa che installi. In Angular è parte del framework e si usa ogni giorno.

ng new gestionale --standalone
ng generate component prodotti
ng generate service prodotti
ng serve
ng build
ng test

Non è solo comodità: ng generate crea file, classe, template e test secondo le convenzioni del progetto. È uno dei meccanismi con cui Angular impone uniformità.

Il pezzo sottovalutato è ng update, che aggiorna il framework e modifica automaticamente il tuo codice dove qualcosa è cambiato tra una versione e l'altra. Su un progetto di cinque anni è la differenza tra aggiornare e riscrivere.

Errori comuni che fanno perdere ore

Non chiudere le sottoscrizioni. Un subscribe() non chiuso quando il componente sparisce resta attivo: perdite di memoria e codice che gira su componenti che non esistono più. La soluzione moderna è non chiamarlo a mano — usa la pipe async nel template, o takeUntilDestroyed():

// nel template: Angular si iscrive e si disiscrive da solo
// <p *ngIf="risultati$ | async as r">{{ r.length }} risultati</p>

Iscriversi dentro un'altra sottoscrizione. Una subscribe annidata è quasi sempre un switchMap scritto male, con lo stesso bug delle risposte fuori ordine.

Usare RxJS per cose che non sono flussi. Un contatore non ha bisogno di un BehaviorSubject: oggi è un signal.

Mutare un array invece di sostituirlo. Con OnPush — la configurazione consigliata — un push non fa aggiornare nulla. Crea un nuovo array.

Portarsi dietro i moduli su un progetto nuovo. Molte guide sono ancora scritte per l'epoca NgModule.

Partire da Angular senza TypeScript. Metà della confusione iniziale è confusione sul linguaggio, non sul framework.

Quando Angular è la scelta giusta

Angular è adattoAngular è una zavorra
Dimensione del teamNumeroso, con ricambioUna o due persone
Durata del progettoAnni, con manutenzionePoche settimane
Tipo di applicazioneGestionale, dashboard, back officeSito vetrina, blog, landing
ContestoAzienda, consulenza, settore regolatoProdotto da validare in fretta
Cosa conta di piùUniformità e prevedibilitàVelocità e leggerezza

Angular è la scelta giusta quando l'uniformità vale più della libertà: gestionale con centinaia di schermate, team di dieci persone che cambiano nel tempo, progetto che qualcuno manutterrà tra sei anni, azienda che lavora già in ambiente Java o .NET. Lì quello che sembra sovrastruttura è esattamente ciò che serve.

È una zavorra quando sei solo e il progetto è piccolo. Per un MVP da validare in tre settimane, l'impalcatura ti costa tempo prima di restituirti qualcosa. Per un sito vetrina non serve nessun framework a componenti.

Sul mercato italiano: Angular è ben presente nella consulenza e nelle aziende grandi, meno nelle startup. Meno offerte di React, più di Vue — il confronto completo è in React, Vue o Angular.

In sintesi

Angular è un framework completo e opinionato: ti dà tutto già deciso e ti chiede di seguire le sue convenzioni, e il valore sta lì — non nella libertà, ma nella prevedibilità.

TypeScript non è opzionale, e va imparato prima del framework, non insieme.

L'iniezione delle dipendenze è solo questo: non costruisci i tuoi servizi, li chiedi. In cambio hai una sola istanza condivisa dove serve e test facili da scrivere.

RxJS è il vero scoglio, ma pesa meno di prima. Con i Signals gestisci lo stato dell'interfaccia senza toccarlo, e impari gli Observable quando ti serve coordinare eventi nel tempo.

Gli standalone component hanno tolto la burocrazia dei moduli. Su un progetto nuovo si parte da lì.

Scegli Angular per progetti lunghi, team numerosi e applicazioni gestionali. Su un progetto piccolo fatto da solo, l'impalcatura non ti restituisce quello che ti costa.

Per capire come si posiziona rispetto agli altri due, vedi React, Vue o Angular. Per inquadrare la scelta nel progetto completo, come scegliere lo stack per una web app.