HTML CSS JAVASCRIPT SQL MYSQL PYTHON JAVA PHP C C++ C# PACKET TRACER CYBERSECURITY REACT TYPESCRIPT NODE.JS GIT & GITHUB DATA SCIENCE BOOTSTRAP GO KOTLIN JQUERY DJANGO VUE ANGULAR MONGODB POSTGRESQL SASS NUMPY PANDAS SCIPY DSA RUST SWIFT BASH XML W3.CSS ANGULARJS WORD POWERPOINT
Corso gratuito

Corso AngularJS in italiano

Il framework JavaScript di Google per applicazioni web dinamiche. Impara le direttive, i controller, lo scope, i servizi, il data binding bidirezionale, le form con validazione, le animazioni e il routing. Con esempi pratici e interattivi.

Introduzione a AngularJS

AngularJS è un framework JavaScript open source sviluppato da Google che estende l'HTML con nuovi attributi e rende le pagine web dinamiche senza riscrivere la struttura. È la versione 1.x del framework Angular, ancora ampiamente usata in progetti legacy.

CaratteristicaDescrizione
MVCSepara Model, View e Controller
Data BindingSincronizzazione automatica tra modello e vista
DirettiveEstende l'HTML con nuovi attributi e tag
Dependency InjectionGestione automatica delle dipendenze
TestabileProgettato per il testing unitario
⚠️ Attenzione: AngularJS (v1.x) ha raggiunto la fine del supporto ufficiale nel dicembre 2021. Per nuovi progetti si raccomanda Angular moderno (v2+). AngularJS rimane importante per manutenere applicazioni esistenti.

Setup: includere AngularJS

HTML β€” primo esempio AngularJS
<!DOCTYPE html>
<html ng-app>
<head>
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.8.3/angular.min.js"></script>
</head>
<body>

<p>Nome: <input type="text" ng-model="nome"></p>
<p>Ciao, {{ nome }}!</p>

</body>
</html>

L'attributo ng-app dice ad AngularJS di controllare quella porzione di pagina. Le doppie graffe {{ }} visualizzano valori del modello. ng-model crea il binding bidirezionale: modifica il campo e il testo si aggiorna istantaneamente.

Espressioni

Le espressioni AngularJS sono scritte tra doppie graffe {{ espressione }}. Possono contenere operatori matematici, stringhe, oggetti e array β€” ma non strutture di controllo come if o loop.

HTML β€” espressioni
<!DOCTYPE html>
<html ng-app>
<head>
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.8.3/angular.min.js"></script>
</head>
<body>

<!-- Operazioni matematiche -->
<p>5 + 3 = {{ 5 + 3 }}</p>
<p>10 * 4 = {{ 10 * 4 }}</p>

<!-- Stringhe -->
<p>{{ "Ciao" + " " + "Mondo!" }}</p>

<!-- Oggetto -->
<p ng-init="persona = {nome:'Marco', eta:30}">
  {{ persona.nome }} ha {{ persona.eta }} anni.
</p>

<!-- Array -->
<p ng-init="corsi=['HTML','CSS','JavaScript']">
  Terzo corso: {{ corsi[2] }}
</p>

</body>
</html>
πŸ“‹ ng-init inizializza variabili direttamente nel template. È comodo per esempi rapidi, ma nella pratica i dati vanno definiti nel Controller.

Moduli

Un modulo AngularJS Γ¨ il contenitore dell'applicazione. Si crea con angular.module() e si collega alla pagina tramite ng-app="nomeModulo".

HTML + JS β€” creare un modulo
<!DOCTYPE html>
<html ng-app="miaApp">
<head>
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.8.3/angular.min.js"></script>
</head>
<body>

<div ng-controller="MioController">
  <h2>{{ messaggio }}</h2>
  <p>Versione: {{ versione }}</p>
</div>

<script>
// Crea il modulo
var app = angular.module('miaApp', []);

// Aggiunge un controller al modulo
app.controller('MioController', function($scope) {
  $scope.messaggio = 'Benvenuto in AngularJS!';
  $scope.versione  = '1.8.3';
});
</script>

</body>
</html>

Il secondo parametro di angular.module() Γ¨ un array di dipendenze. Un array vuoto [] significa che il modulo non dipende da altri moduli.

Direttive

Le direttive sono attributi HTML speciali che iniziano con ng-. Estendono l'HTML aggiungendo comportamenti dinamici. AngularJS ne include decine, e puoi crearne di personalizzate.

DirettivaFunzione
ng-appInizializza l'applicazione AngularJS
ng-modelBinding bidirezionale con un campo input
ng-controllerCollega un controller alla vista
ng-repeatRipete un elemento HTML per ogni item di una lista
ng-ifMostra/nasconde un elemento in base a una condizione
ng-show / ng-hideMostra/nasconde (con display) in base a una condizione
ng-clickEsegue codice al click
ng-classAggiunge classi CSS dinamicamente
ng-styleApplica stili inline dinamicamente
ng-initInizializza variabili di scope
HTML β€” direttive ng-repeat e ng-if
<!DOCTYPE html>
<html ng-app="miaApp">
<head>
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.8.3/angular.min.js"></script>
</head>
<body>
<div ng-controller="ListaCtrl">

  <h3>I miei corsi:</h3>
  <ul>
    <li ng-repeat="corso in corsi">
      {{ corso.nome }}
      <span ng-if="corso.completato"> βœ…</span>
      <span ng-if="!corso.completato"> πŸ”„</span>
    </li>
  </ul>

  <p ng-show="mostraTotale">
    Totale corsi: {{ corsi.length }}
  </p>
  <button ng-click="mostraTotale = !mostraTotale">Mostra/Nascondi totale</button>

</div>
<script>
angular.module('miaApp', []).controller('ListaCtrl', function($scope) {
  $scope.corsi = [
    { nome: 'HTML', completato: true },
    { nome: 'CSS',  completato: true },
    { nome: 'AngularJS', completato: false }
  ];
  $scope.mostraTotale = false;
});
</script>
</body>
</html>

ng-model

ng-model crea il data binding bidirezionale tra un campo di input e una variabile dello scope. Ogni modifica al campo aggiorna istantaneamente il modello, e viceversa.

HTML β€” ng-model e binding in tempo reale
<!DOCTYPE html>
<html ng-app="miaApp">
<head>
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.8.3/angular.min.js"></script>
  <style>
    body { font-family: Arial, sans-serif; padding: 20px; }
    input { padding: 8px; margin: 5px 0; border: 1px solid #ccc; border-radius: 4px; width: 100%; }
    .anteprima { background: #f0f4ff; padding: 16px; border-radius: 8px; margin-top: 12px; }
  </style>
</head>
<body>
<div ng-controller="ModelloCtrl">

  <label>Nome:</label>
  <input type="text" ng-model="nome" placeholder="Inserisci nome">

  <label>Cognome:</label>
  <input type="text" ng-model="cognome" placeholder="Inserisci cognome">

  <label>EtΓ :</label>
  <input type="number" ng-model="eta" placeholder="EtΓ ">

  <div class="anteprima">
    <strong>Anteprima in tempo reale:</strong><br>
    {{ nome }} {{ cognome }}, {{ eta }} anni
  </div>

</div>
<script>
angular.module('miaApp', []).controller('ModelloCtrl', function($scope) {
  $scope.nome    = 'Marco';
  $scope.cognome = 'Rossi';
  $scope.eta     = 30;
});
</script>
</body>
</html>

Data Binding

Il data binding Γ¨ il meccanismo che sincronizza automaticamente il modello (dati JavaScript) con la vista (HTML). AngularJS usa il binding bidirezionale: ogni cambiamento in uno si riflette nell'altro senza codice aggiuntivo.

HTML β€” calcolatrice con data binding
<!DOCTYPE html>
<html ng-app>
<head>
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.8.3/angular.min.js"></script>
  <style>
    body { font-family: Arial, sans-serif; padding: 20px; }
    input { width: 80px; padding: 8px; font-size: 1.1rem; text-align: center; }
    .risultato { font-size: 1.4rem; font-weight: bold; color: #4f46e5; margin-top: 16px; }
  </style>
</head>
<body>

<h2>Calcolatrice live</h2>
<input type="number" ng-model="a" ng-init="a=10">
 + 
<input type="number" ng-model="b" ng-init="b=5">

<div class="risultato">
  Risultato: {{ a * 1 + b * 1 }}
</div>

<p>Somma: {{ a * 1 + b * 1 }}</p>
<p>Differenza: {{ a - b }}</p>
<p>Prodotto: {{ a * b }}</p>
<p>Divisione: {{ (b != 0) ? (a / b | number:2) : 'Divisione per zero!' }}</p>

</body>
</html>

Controller

Il controller Γ¨ una funzione JavaScript che gestisce i dati e la logica della vista. Usa $scope per esporre variabili e funzioni all'HTML.

HTML β€” controller con metodi
<!DOCTYPE html>
<html ng-app="negozio">
<head>
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.8.3/angular.min.js"></script>
  <style>
    body { font-family: Arial, sans-serif; padding: 20px; }
    button { padding: 8px 16px; margin: 4px; cursor: pointer; border: none; border-radius: 4px; }
    .aggiungi { background: #4f46e5; color: #fff; }
    .rimuovi  { background: #ef4444; color: #fff; }
    .carrello { background: #f0fdf4; padding: 16px; border-radius: 8px; margin-top: 12px; }
  </style>
</head>
<body>
<div ng-controller="NegozioCtrl">

  <h2>πŸ›’ Carrello ({{ carrello.length }} prodotti)</h2>

  <div ng-repeat="prodotto in prodotti">
    {{ prodotto.nome }} β€” €{{ prodotto.prezzo }}
    <button class="aggiungi" ng-click="aggiungi(prodotto)">+ Aggiungi</button>
  </div>

  <div class="carrello">
    <strong>Nel carrello:</strong>
    <p ng-repeat="item in carrello">{{ item.nome }} β€” €{{ item.prezzo }}</p>
    <p ng-if="carrello.length === 0">Carrello vuoto</p>
    <strong>Totale: €{{ totale() }}</strong>
    <br><button class="rimuovi" ng-click="svuota()">Svuota carrello</button>
  </div>

</div>
<script>
angular.module('negozio', []).controller('NegozioCtrl', function($scope) {
  $scope.prodotti = [
    { nome: 'Laptop', prezzo: 899 },
    { nome: 'Mouse',  prezzo: 25  },
    { nome: 'Tastiera', prezzo: 55 }
  ];
  $scope.carrello = [];
  $scope.aggiungi = function(p) { $scope.carrello.push(p); };
  $scope.svuota   = function()  { $scope.carrello = [];    };
  $scope.totale   = function()  {
    return $scope.carrello.reduce(function(sum, p) { return sum + p.prezzo; }, 0);
  };
});
</script>
</body>
</html>

Scope

Lo $scope è l'oggetto condiviso tra controller e vista. È il "ponte" che rende disponibili dati e funzioni all'HTML. Esiste uno scope radice ($rootScope) accessibile da tutta l'applicazione, e scope locali per ogni controller.

HTML β€” scope padre e figlio
<!DOCTYPE html>
<html ng-app="scopeApp">
<head>
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.8.3/angular.min.js"></script>
  <style>
    body { font-family: Arial; padding: 16px; }
    .padre { border: 2px solid #4f46e5; padding: 16px; border-radius: 8px; }
    .figlio { border: 2px solid #0d9488; padding: 12px; border-radius: 8px; margin-top: 12px; }
  </style>
</head>
<body>
<div ng-controller="PadreCtrl" class="padre">
  <strong>Scope Padre</strong>
  <p>Nome padre: {{ nomePadre }}</p>

  <div ng-controller="FiglioCtrl" class="figlio">
    <strong>Scope Figlio</strong>
    <p>Eredita dal padre: {{ nomePadre }}</p>
    <p>Proprio del figlio: {{ nomeFiglio }}</p>
  </div>
</div>

<script>
angular.module('scopeApp', [])
  .controller('PadreCtrl', function($scope) {
    $scope.nomePadre = 'Mario';
  })
  .controller('FiglioCtrl', function($scope) {
    $scope.nomeFiglio = 'Luigi';
  });
</script>
</body>
</html>
πŸ’‘ Lo scope figlio eredita le proprietΓ  dello scope padre (prototypal inheritance di JavaScript). Se lo scope figlio modifica una proprietΓ  ereditata, crea una copia locale senza modificare il padre.

Filtri

I filtri trasformano i dati prima che vengano mostrati nella vista. Si applicano con il carattere pipe | nelle espressioni o nel codice JS.

FiltroEffettoEsempio
uppercaseTutto maiuscolo{{ testo | uppercase }}
lowercaseTutto minuscolo{{ testo | lowercase }}
currencyFormato valuta{{ prezzo | currency:"€" }}
numberDecimali fissi{{ num | number:2 }}
dateFormato data{{ data | date:"dd/MM/yyyy" }}
orderByOrdina arrayng-repeat="x in arr | orderBy:'nome'"
filterFiltra arrayng-repeat="x in arr | filter:cerca"
limitToLimita elementing-repeat="x in arr | limitTo:3"
HTML β€” ricerca e filtro in tempo reale
<!DOCTYPE html>
<html ng-app="filtroApp">
<head>
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.8.3/angular.min.js"></script>
  <style>
    body { font-family: Arial; padding: 16px; }
    input { padding: 8px; width: 100%; border: 1px solid #ccc; border-radius: 4px; margin-bottom: 12px; }
    th { cursor: pointer; background: #4f46e5; color: #fff; padding: 8px; }
    td { padding: 6px 8px; border-bottom: 1px solid #eee; }
  </style>
</head>
<body>
<div ng-controller="FiltroCtrl">

  <input type="text" ng-model="cerca" placeholder="πŸ” Cerca prodotto...">

  <table>
    <tr>
      <th ng-click="ordine='nome'">Nome ↕</th>
      <th ng-click="ordine='prezzo'">Prezzo ↕</th>
    </tr>
    <tr ng-repeat="p in prodotti | filter:cerca | orderBy:ordine">
      <td>{{ p.nome }}</td>
      <td>{{ p.prezzo | currency:"€" }}</td>
    </tr>
  </table>

</div>
<script>
angular.module('filtroApp', []).controller('FiltroCtrl', function($scope) {
  $scope.ordine = 'nome';
  $scope.prodotti = [
    { nome: 'Laptop',    prezzo: 899 },
    { nome: 'Tablet',    prezzo: 350 },
    { nome: 'Smartphone',prezzo: 599 },
    { nome: 'Monitor',   prezzo: 299 },
    { nome: 'Tastiera',  prezzo: 55  }
  ];
});
</script>
</body>
</html>

Tabelle e ng-repeat

ng-repeat Γ¨ la direttiva piΓΉ usata in AngularJS per generare liste e tabelle dinamiche iterando su array di dati.

HTML β€” tabella dinamica con ng-repeat
<!DOCTYPE html>
<html ng-app="tabellaApp">
<head>
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.8.3/angular.min.js"></script>
  <style>
    body { font-family: Arial; padding: 16px; }
    table { border-collapse: collapse; width: 100%; }
    th { background: #1e293b; color: #fff; padding: 10px; }
    td { padding: 8px 10px; border-bottom: 1px solid #e2e8f0; }
    tr:nth-child(even) { background: #f8fafc; }
    tr:hover { background: #e0f2fe; }
    .badge { display:inline-block; padding: 2px 8px; border-radius:99px; font-size:.8rem; font-weight:700; }
    .si   { background:#dcfce7; color:#166534; }
    .no   { background:#fee2e2; color:#991b1b; }
  </style>
</head>
<body>
<div ng-controller="TabellaCtrl">

  <h2>Studenti iscritti</h2>
  <table>
    <tr>
      <th>#</th>
      <th>Nome</th>
      <th>Voto</th>
      <th>Promosso</th>
    </tr>
    <tr ng-repeat="s in studenti">
      <td>{{ $index + 1 }}</td>
      <td>{{ s.nome }}</td>
      <td>{{ s.voto }}</td>
      <td>
        <span class="badge" ng-class="s.voto >= 6 ? 'si' : 'no'">
          {{ s.voto >= 6 ? 'Sì' : 'No' }}
        </span>
      </td>
    </tr>
  </table>

</div>
<script>
angular.module('tabellaApp', []).controller('TabellaCtrl', function($scope) {
  $scope.studenti = [
    { nome: 'Alice',   voto: 9 },
    { nome: 'Marco',   voto: 5 },
    { nome: 'Sofia',   voto: 8 },
    { nome: 'Luca',    voto: 4 },
    { nome: 'Giulia',  voto: 7 }
  ];
});
</script>
</body>
</html>
πŸ’‘ Variabili speciali in ng-repeat: $index (indice corrente), $first, $last, $even, $odd (booleani).

Select

AngularJS semplifica la creazione di menu select dinamici con ng-options, che genera le opzioni da un array.

HTML β€” select con ng-options
<!DOCTYPE html>
<html ng-app="selectApp">
<head>
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.8.3/angular.min.js"></script>
  <style>
    body { font-family: Arial; padding: 20px; }
    select { padding: 8px; font-size: 1rem; border-radius: 4px; width: 100%; margin: 8px 0; }
    .card  { background: #f0f4ff; padding: 16px; border-radius: 8px; margin-top: 12px; }
  </style>
</head>
<body>
<div ng-controller="SelectCtrl">

  <label>Scegli un corso:</label>
  <select ng-model="corsoScelto"
          ng-options="c.nome for c in corsi">
    <option value="">-- Seleziona --</option>
  </select>

  <div class="card" ng-if="corsoScelto">
    <h3>{{ corsoScelto.nome }}</h3>
    <p>Durata: {{ corsoScelto.ore }} ore</p>
    <p>DifficoltΓ : {{ corsoScelto.livello }}</p>
  </div>

</div>
<script>
angular.module('selectApp', []).controller('SelectCtrl', function($scope) {
  $scope.corsi = [
    { nome: 'HTML & CSS',    ore: 20, livello: 'Principiante' },
    { nome: 'JavaScript',    ore: 40, livello: 'Intermedio'   },
    { nome: 'AngularJS',     ore: 35, livello: 'Intermedio'   },
    { nome: 'Node.js',       ore: 30, livello: 'Avanzato'     }
  ];
  $scope.corsoScelto = null;
});
</script>
</body>
</html>

Servizi

I servizi AngularJS sono oggetti singleton riutilizzabili tra i controller. AngularJS include servizi predefiniti (come $http, $timeout, $interval) e permette di crearne di personalizzati.

HTML β€” $timeout e $interval
<!DOCTYPE html>
<html ng-app="servizioApp">
<head>
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.8.3/angular.min.js"></script>
  <style>
    body { font-family: Arial; padding: 20px; }
    .orologio { font-size: 2.5rem; font-weight: bold; color: #4f46e5; }
    button { padding: 8px 16px; margin: 6px 4px; cursor: pointer; border-radius: 4px; border: none; background: #4f46e5; color: #fff; }
  </style>
</head>
<body>
<div ng-controller="ServizioCtrl">

  <h2>⏱ Orologio live</h2>
  <div class="orologio">{{ ora }}</div>

  <button ng-click="avvia()">β–Ά Avvia</button>
  <button ng-click="ferma()">⏹ Ferma</button>

  <p>Contatore clic sul Avvia: {{ clic }}</p>

</div>
<script>
angular.module('servizioApp', [])
  .controller('ServizioCtrl', function($scope, $interval, $filter) {
    var timer;
    $scope.clic = 0;

    function aggiorna() {
      $scope.ora = $filter('date')(new Date(), 'HH:mm:ss');
    }
    aggiorna();

    $scope.avvia = function() {
      if (!timer) {
        $scope.clic++;
        timer = $interval(aggiorna, 1000);
      }
    };
    $scope.ferma = function() {
      if (timer) { $interval.cancel(timer); timer = null; }
    };
  });
</script>
</body>
</html>

Servizio personalizzato con factory

JS β€” factory personalizzata
<!DOCTYPE html>
<html ng-app="factoryApp">
<head>
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.8.3/angular.min.js"></script>
  <style> body { font-family: Arial; padding: 20px; } </style>
</head>
<body>
<div ng-controller="CalcoloCtrl">
  <h2>IVA Calculator</h2>
  Prezzo netto: <input type="number" ng-model="netto" ng-init="netto=100">
  <p>IVA (22%): €{{ iva.calcola(netto) | number:2 }}</p>
  <p>Totale: €{{ iva.totale(netto) | number:2 }}</p>
</div>

<script>
var app = angular.module('factoryApp', []);

// Factory personalizzata
app.factory('iva', function() {
  return {
    calcola: function(n) { return n * 0.22; },
    totale:  function(n) { return n * 1.22; }
  };
});

// Controller che usa la factory
app.controller('CalcoloCtrl', function($scope, iva) {
  $scope.iva = iva;
  $scope.netto = 100;
});
</script>
</body>
</html>

$http

Il servizio $http esegue richieste HTTP (AJAX) verso API esterne o file JSON locali. Restituisce una promise con i metodi .then() e .catch().

HTML β€” $http GET da API pubblica
<!DOCTYPE html>
<html ng-app="httpApp">
<head>
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.8.3/angular.min.js"></script>
  <style>
    body { font-family: Arial; padding: 20px; }
    .post { border: 1px solid #e2e8f0; padding: 12px; border-radius: 8px; margin: 8px 0; }
    .post h4 { margin: 0 0 6px; color: #4f46e5; text-transform: capitalize; }
    .caricamento { color: #64748b; font-style: italic; }
    button { padding: 8px 16px; background: #4f46e5; color: #fff; border: none; border-radius: 4px; cursor: pointer; }
  </style>
</head>
<body>
<div ng-controller="HttpCtrl">

  <h2>Post da JSONPlaceholder API</h2>
  <button ng-click="carica()">πŸ“₯ Carica post</button>

  <p class="caricamento" ng-if="caricamento">Caricamento in corso...</p>
  <p ng-if="errore" style="color:red">Errore: {{ errore }}</p>

  <div class="post" ng-repeat="p in posts | limitTo:5">
    <h4>{{ p.title }}</h4>
    <p>{{ p.body }}</p>
  </div>

</div>
<script>
angular.module('httpApp', []).controller('HttpCtrl', function($scope, $http) {
  $scope.posts      = [];
  $scope.caricamento = false;
  $scope.errore     = null;

  $scope.carica = function() {
    $scope.caricamento = true;
    $scope.errore = null;
    $http.get('https://jsonplaceholder.typicode.com/posts')
      .then(function(risposta) {
        $scope.posts = risposta.data;
      })
      .catch(function(err) {
        $scope.errore = 'Impossibile caricare i dati.';
      })
      .finally(function() {
        $scope.caricamento = false;
      });
  };
});
</script>
</body>
</html>

DOM

AngularJS gestisce il DOM tramite direttive. Le principali per il controllo della visualizzazione sono ng-show, ng-hide, ng-class, ng-style e ng-disabled.

HTML β€” ng-class e ng-style dinamici
<!DOCTYPE html>
<html ng-app="domApp">
<head>
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.8.3/angular.min.js"></script>
  <style>
    body { font-family: Arial; padding: 20px; }
    .box  { padding: 20px; border-radius: 8px; margin: 10px 0; transition: all 0.3s; text-align: center; font-size: 1.2rem; font-weight: bold; }
    .verde  { background: #dcfce7; color: #166534; }
    .rosso  { background: #fee2e2; color: #991b1b; }
    .blu    { background: #dbeafe; color: #1e40af; }
    input[type=range] { width: 100%; }
    button { padding: 8px 14px; margin: 4px; border: none; border-radius: 4px; cursor: pointer; }
  </style>
</head>
<body>
<div ng-controller="DomCtrl">

  <!-- ng-class con oggetto -->
  <div class="box" ng-class="{verde: stato=='ok', rosso: stato=='errore', blu: stato=='info'}">
    Stato: {{ stato }}
  </div>
  <button ng-click="stato='ok'">βœ… OK</button>
  <button ng-click="stato='errore'">❌ Errore</button>
  <button ng-click="stato='info'">ℹ️ Info</button>

  <hr>

  <!-- ng-style dinamico -->
  <p>Dimensione testo: {{ dimensione }}px</p>
  <input type="range" ng-model="dimensione" min="12" max="48">
  <p ng-style="{'font-size': dimensione + 'px', 'color': colore}">
    Testo dinamico con AngularJS!
  </p>
  <button ng-click="colore='#4f46e5'">Viola</button>
  <button ng-click="colore='#dc2626'">Rosso</button>
  <button ng-click="colore='#16a34a'">Verde</button>

</div>
<script>
angular.module('domApp', []).controller('DomCtrl', function($scope) {
  $scope.stato     = 'info';
  $scope.dimensione = 20;
  $scope.colore    = '#4f46e5';
});
</script>
</body>
</html>

Eventi

AngularJS offre direttive per gestire tutti gli eventi del mouse e della tastiera senza usare addEventListener direttamente.

DirettivaEvento corrispondente
ng-clickclick del mouse
ng-dblclickdoppio click
ng-mouseenter / ng-mouseleavehover del mouse
ng-keydown / ng-keyuptasto premuto/rilasciato
ng-changevalore di input cambiato
ng-submitinvio del form
ng-focus / ng-blurfocus/perdita focus su input
HTML β€” eventi mouse e tastiera
<!DOCTYPE html>
<html ng-app="eventiApp">
<head>
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.8.3/angular.min.js"></script>
  <style>
    body { font-family: Arial; padding: 20px; }
    .zona { width: 200px; height: 100px; display: flex; align-items: center; justify-content: center;
            border-radius: 8px; font-weight: bold; cursor: pointer; transition: all .2s; }
    .normale { background: #e0e7ff; color: #3730a3; }
    .hover   { background: #4f46e5; color: #fff; }
    input    { padding: 8px; width: 100%; border: 1px solid #ccc; border-radius: 4px; margin: 8px 0; }
    .log     { background: #f8fafc; border: 1px solid #e2e8f0; border-radius: 6px; padding: 8px; height: 80px; overflow-y: auto; font-size: .85rem; }
  </style>
</head>
<body>
<div ng-controller="EventiCtrl">

  <div class="zona"
       ng-class="dentro ? 'hover' : 'normale'"
       ng-mouseenter="dentro=true; aggiungiLog('Entrato!')"
       ng-mouseleave="dentro=false; aggiungiLog('Uscito!')"
       ng-click="aggiungiLog('Click! Contatore: ' + ++clic)">
    {{ dentro ? 'πŸ–±οΈ Dentro!' : 'Passa il mouse' }}
  </div>

  <input type="text" ng-model="testo"
         ng-keyup="aggiungiLog('Tasto: ' + $event.key)"
         placeholder="Digita qualcosa...">

  <p>Caratteri: {{ testo.length }}</p>

  <div class="log">
    <div ng-repeat="riga in log track by $index">{{ riga }}</div>
  </div>

</div>
<script>
angular.module('eventiApp', []).controller('EventiCtrl', function($scope) {
  $scope.log   = [];
  $scope.clic  = 0;
  $scope.testo = '';
  $scope.aggiungiLog = function(msg) {
    $scope.log.unshift(msg);
    if ($scope.log.length > 10) $scope.log.pop();
  };
});
</script>
</body>
</html>

Form

AngularJS gestisce i form automaticamente: ogni form ottiene un oggetto di stato con proprietΓ  che indicano se Γ¨ stato modificato ($dirty), valido ($valid), toccato ($touched) e altri.

HTML β€” form con stato AngularJS
<!DOCTYPE html>
<html ng-app="formApp">
<head>
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.8.3/angular.min.js"></script>
  <style>
    body { font-family: Arial; padding: 20px; max-width: 500px; }
    input, textarea { width: 100%; padding: 8px; margin: 4px 0 12px; border: 1px solid #ccc; border-radius: 4px; box-sizing: border-box; }
    input.ng-invalid.ng-dirty { border-color: #ef4444; background: #fef2f2; }
    input.ng-valid.ng-dirty   { border-color: #22c55e; background: #f0fdf4; }
    button { padding: 10px 24px; background: #4f46e5; color: #fff; border: none; border-radius: 4px; cursor: pointer; }
    button:disabled { background: #94a3b8; cursor: not-allowed; }
    .stato { font-size: .85rem; color: #64748b; margin-top: 8px; }
  </style>
</head>
<body>
<div ng-controller="FormCtrl">

  <h2>Registrazione</h2>

  <form name="regForm" ng-submit="invia(regForm)">
    <label>Nome *</label>
    <input type="text" name="nome" ng-model="utente.nome"
           required minlength="3" placeholder="Minimo 3 caratteri">

    <label>Email *</label>
    <input type="email" name="email" ng-model="utente.email"
           required placeholder="nome@esempio.it">

    <label>EtΓ </label>
    <input type="number" name="eta" ng-model="utente.eta"
           min="18" max="99" placeholder="18-99">

    <button type="submit" ng-disabled="regForm.$invalid">
      Registrati
    </button>

    <p class="stato">
      Form valido: {{ regForm.$valid ? 'βœ…' : '❌' }} |
      Modificato: {{ regForm.$dirty ? 'Sì' : 'No' }}
    </p>
  </form>

  <div ng-if="inviato" style="background:#dcfce7;padding:12px;border-radius:8px;margin-top:12px">
    βœ… Benvenuto, <strong>{{ utente.nome }}</strong>! ({{ utente.email }})
  </div>

</div>
<script>
angular.module('formApp', []).controller('FormCtrl', function($scope) {
  $scope.utente  = {};
  $scope.inviato = false;
  $scope.invia   = function(form) {
    if (form.$valid) { $scope.inviato = true; }
  };
});
</script>
</body>
</html>

Validazione

AngularJS valida automaticamente i campi HTML5 (required, min, max, minlength, maxlength, pattern) e aggiunge classi CSS per mostrare lo stato.

ProprietΓ Significato
$valid / $invalidCampo/form valido o no
$dirty / $pristineCampo modificato o intatto
$touched / $untouchedCampo toccato (focus poi blur) o no
$errorOggetto con i tipi di errore attivi
HTML β€” messaggi di errore personalizzati
<!DOCTYPE html>
<html ng-app="valApp">
<head>
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.8.3/angular.min.js"></script>
  <style>
    body { font-family: Arial; padding: 20px; max-width: 460px; }
    input { width: 100%; padding: 8px; border: 1px solid #ccc; border-radius: 4px;
            margin: 4px 0; box-sizing: border-box; }
    input.ng-invalid.ng-touched { border-color: #ef4444; }
    input.ng-valid.ng-touched   { border-color: #22c55e; }
    .errore { color: #ef4444; font-size: .85rem; margin: 0 0 10px; }
  </style>
</head>
<body>
<div ng-controller="ValCtrl">
  <form name="f">

    <label>Username</label>
    <input type="text" name="user" ng-model="user"
           required minlength="4" maxlength="12"
           pattern="[a-zA-Z0-9]+">
    <p class="errore" ng-if="f.user.$touched && f.user.$error.required">
      ⚠️ Username obbligatorio.
    </p>
    <p class="errore" ng-if="f.user.$touched && f.user.$error.minlength">
      ⚠️ Minimo 4 caratteri.
    </p>
    <p class="errore" ng-if="f.user.$touched && f.user.$error.pattern">
      ⚠️ Solo lettere e numeri.
    </p>

    <label>Password</label>
    <input type="password" name="pwd" ng-model="pwd"
           required minlength="8">
    <p class="errore" ng-if="f.pwd.$touched && f.pwd.$error.required">
      ⚠️ Password obbligatoria.
    </p>
    <p class="errore" ng-if="f.pwd.$touched && f.pwd.$error.minlength">
      ⚠️ Minimo 8 caratteri.
    </p>

    <button ng-disabled="f.$invalid" style="padding:10px 20px;background:#4f46e5;color:#fff;border:none;border-radius:4px;cursor:pointer">
      Registrati
    </button>

  </form>
</div>
<script>angular.module('valApp',[]).controller('ValCtrl',function($scope){});</script>
</body>
</html>

Animazioni

Il modulo ngAnimate aggiunge animazioni CSS automaticamente quando le direttive AngularJS mostrano o nascondono elementi. Basta includere il modulo e definire le classi CSS.

HTML β€” animazioni con ngAnimate
<!DOCTYPE html>
<html ng-app="animApp">
<head>
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.8.3/angular.min.js"></script>
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.8.3/angular-animate.min.js"></script>
  <style>
    body { font-family: Arial; padding: 20px; }
    .box { padding: 20px; background: #4f46e5; color: #fff; border-radius: 8px;
           margin: 12px 0; font-size: 1.1rem; font-weight: bold; text-align: center; }

    /* Animazione ng-show/ng-hide */
    .box.ng-hide-add    { animation: fadeOut 0.4s; }
    .box.ng-hide-remove { animation: fadeIn  0.4s; }

    /* Animazione ng-repeat */
    .item.ng-enter { animation: slideIn 0.4s; }
    .item.ng-leave { animation: slideOut 0.3s; }

    @keyframes fadeIn   { from { opacity:0; transform:scale(.9); } to { opacity:1; transform:scale(1); } }
    @keyframes fadeOut  { from { opacity:1; } to { opacity:0; } }
    @keyframes slideIn  { from { opacity:0; transform:translateX(-20px); } to { opacity:1; transform:none; } }
    @keyframes slideOut { from { opacity:1; } to { opacity:0; transform:translateX(20px); } }

    button { padding: 8px 16px; margin: 4px; border: none; border-radius: 4px; cursor: pointer;
             background: #4f46e5; color: #fff; }
    .item  { padding: 8px 12px; border: 1px solid #e2e8f0; border-radius: 6px; margin: 4px 0; }
  </style>
</head>
<body>
<div ng-controller="AnimCtrl">

  <button ng-click="visibile = !visibile">Toggle banner</button>
  <div class="box" ng-show="visibile">πŸŽ‰ Animazione con ngAnimate!</div>

  <hr>
  <button ng-click="aggiungi()">+ Aggiungi</button>
  <button ng-click="rimuovi()">- Rimuovi</button>
  <div class="item" ng-repeat="i in items">Elemento {{ i }}</div>

</div>
<script>
angular.module('animApp', ['ngAnimate']).controller('AnimCtrl', function($scope) {
  $scope.visibile = true;
  $scope.items = [1, 2, 3];
  var cnt = 4;
  $scope.aggiungi = function() { $scope.items.push(cnt++); };
  $scope.rimuovi  = function() { if ($scope.items.length) $scope.items.pop(); };
});
</script>
</body>
</html>

Routing

Il modulo ngRoute permette di creare applicazioni Single Page (SPA) con navigazione tramite URL #/percorso senza ricaricare la pagina.

HTML β€” SPA con ngRoute
<!DOCTYPE html>
<html ng-app="routeApp">
<head>
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.8.3/angular.min.js"></script>
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.8.3/angular-route.min.js"></script>
  <style>
    body { font-family: Arial; padding: 0; margin: 0; }
    nav  { background: #1e293b; padding: 12px 20px; }
    nav a { color: #94a3b8; text-decoration: none; margin-right: 16px; font-weight: bold; }
    nav a:hover { color: #fff; }
    .pagina { padding: 30px; }
    h2 { color: #4f46e5; }
  </style>
</head>
<body>

<nav>
  <a href="#/">🏠 Home</a>
  <a href="#/chi-sono">πŸ‘€ Chi sono</a>
  <a href="#/contatti">βœ‰οΈ Contatti</a>
</nav>

<!-- Qui ngRoute inietta la vista corrente -->
<div ng-view></div>

<script>
var app = angular.module('routeApp', ['ngRoute']);

app.config(function($routeProvider) {
  $routeProvider
    .when('/', {
      template: '<div class="pagina"><h2>🏠 Home</h2><p>Benvenuto nella nostra SPA con AngularJS!</p></div>'
    })
    .when('/chi-sono', {
      template: '<div class="pagina"><h2>πŸ‘€ Chi sono</h2><p>Sono un developer appassionato di AngularJS.</p></div>'
    })
    .when('/contatti', {
      template: '<div class="pagina"><h2>βœ‰οΈ Contatti</h2><p>Email: info@esempio.it</p></div>'
    })
    .otherwise({ redirectTo: '/' });
});
</script>
</body>
</html>

Include

La direttiva ng-include carica frammenti HTML esterni (file separati) e li inserisce nella pagina. È utile per componenti riutilizzabili come navbar e footer.

HTML β€” ng-include e template inline
<!DOCTYPE html>
<html ng-app="includeApp">
<head>
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.8.3/angular.min.js"></script>
  <style>
    body { font-family: Arial; padding: 20px; }
    .card { border: 1px solid #e2e8f0; padding: 16px; border-radius: 8px; margin: 8px 0; }
    button { padding: 8px 16px; margin: 4px; border: none; border-radius: 4px;
             cursor: pointer; background: #4f46e5; color: #fff; }
  </style>
</head>
<body>
<div ng-controller="IncludeCtrl">

  <h2>Scegli un template</h2>
  <button ng-click="template='tmpl1.html'">Profilo Utente</button>
  <button ng-click="template='tmpl2.html'">Statistiche</button>

  <!-- ng-include carica il template selezionato -->
  <div ng-include="template"></div>

  <!-- Template definiti inline con script type="text/ng-template" -->
  <script type="text/ng-template" id="tmpl1.html">
    <div class="card">
      <h3>πŸ‘€ Profilo: {{ utente.nome }}</h3>
      <p>Email: {{ utente.email }}</p>
      <p>Ruolo: {{ utente.ruolo }}</p>
    </div>
  </script>

  <script type="text/ng-template" id="tmpl2.html">
    <div class="card">
      <h3>πŸ“Š Statistiche</h3>
      <p>Corsi completati: 12</p>
      <p>Ore studiate: 48</p>
      <p>Badge ottenuti: 5</p>
    </div>
  </script>

</div>
<script>
angular.module('includeApp', []).controller('IncludeCtrl', function($scope) {
  $scope.template = 'tmpl1.html';
  $scope.utente = { nome: 'Marco Rossi', email: 'marco@esempio.it', ruolo: 'Studente' };
});
</script>
</body>
</html>

Applicazione Completa

Mettiamo insieme tutto: un'app di gestione contatti con controller, filtri, form con validazione e operazioni CRUD.

HTML β€” app CRUD rubrica contatti
<!DOCTYPE html>
<html ng-app="rubricaApp">
<head>
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.8.3/angular.min.js"></script>
  <style>
    * { box-sizing: border-box; }
    body { font-family: Arial; padding: 20px; background: #f8fafc; }
    h1   { color: #1e293b; }
    .form-box { background: #fff; padding: 20px; border-radius: 8px; margin-bottom: 20px;
                border: 1px solid #e2e8f0; }
    input { width: 100%; padding: 8px; margin: 4px 0 12px; border: 1px solid #cbd5e1;
            border-radius: 4px; }
    input.ng-invalid.ng-dirty { border-color: #ef4444; }
    .btn   { padding: 8px 16px; border: none; border-radius: 4px; cursor: pointer; margin: 2px; }
    .add   { background: #4f46e5; color: #fff; }
    .del   { background: #ef4444; color: #fff; font-size: .8rem; }
    .search { width: 100%; padding: 10px; border: 2px solid #4f46e5; border-radius: 6px;
              font-size: 1rem; margin-bottom: 16px; }
    table  { width: 100%; border-collapse: collapse; background: #fff; border-radius: 8px; overflow:hidden; }
    th     { background: #1e293b; color: #fff; padding: 10px; text-align: left; cursor: pointer; }
    td     { padding: 10px; border-bottom: 1px solid #f1f5f9; }
    tr:hover td { background: #f0f4ff; }
    .vuoto { text-align: center; color: #94a3b8; padding: 20px; }
    .errore { color: #ef4444; font-size: .83rem; margin: -8px 0 8px; }
  </style>
</head>
<body>
<div ng-controller="RubricaCtrl">

  <h1>πŸ“’ Rubrica Contatti</h1>

  <!-- Form aggiunta -->
  <div class="form-box">
    <form name="f" ng-submit="aggiungi(f)" novalidate>
      <input type="text" ng-model="nuovo.nome" placeholder="Nome *"
             required minlength="2">
      <p class="errore" ng-if="f.nome && f.nome.$touched && f.nome.$error.required">Nome obbligatorio</p>

      <input type="email" ng-model="nuovo.email" placeholder="Email *"
             name="email" required>
      <p class="errore" ng-if="f.email.$touched && f.email.$invalid">Email non valida</p>

      <input type="tel" ng-model="nuovo.tel" placeholder="Telefono">

      <button class="btn add" type="submit" ng-disabled="f.$invalid">
        βž• Aggiungi contatto
      </button>
    </form>
  </div>

  <!-- Ricerca -->
  <input class="search" type="text" ng-model="cerca" placeholder="πŸ” Cerca contatto...">

  <table>
    <tr>
      <th ng-click="ordine='nome'">Nome ↕</th>
      <th ng-click="ordine='email'">Email ↕</th>
      <th>Telefono</th>
      <th>Azioni</th>
    </tr>
    <tr ng-repeat="c in contatti | filter:cerca | orderBy:ordine">
      <td>{{ c.nome }}</td>
      <td>{{ c.email }}</td>
      <td>{{ c.tel || 'β€”' }}</td>
      <td><button class="btn del" ng-click="elimina($index)">πŸ—‘ Elimina</button></td>
    </tr>
    <tr ng-if="(contatti | filter:cerca).length === 0">
      <td colspan="4" class="vuoto">Nessun contatto trovato.</td>
    </tr>
  </table>

  <p style="margin-top:12px;color:#64748b">Totale: {{ contatti.length }} contatti</p>

</div>
<script>
angular.module('rubricaApp', []).controller('RubricaCtrl', function($scope) {
  $scope.ordine   = 'nome';
  $scope.nuovo    = {};
  $scope.contatti = [
    { nome: 'Alice Bianchi',  email: 'alice@esempio.it',  tel: '333-111-2222' },
    { nome: 'Marco Rossi',    email: 'marco@esempio.it',  tel: '347-555-6666' },
    { nome: 'Sofia Ferrari',  email: 'sofia@esempio.it',  tel: '' }
  ];
  $scope.aggiungi = function(form) {
    if (form.$valid) {
      $scope.contatti.push(angular.copy($scope.nuovo));
      $scope.nuovo = {};
      form.$setPristine();
    }
  };
  $scope.elimina = function(i) {
    $scope.contatti.splice(i, 1);
  };
});
</script>
</body>
</html>

Esercizi pratici

πŸ† Esercizio 1 β€” Lista della spesa

Crea un'app AngularJS con: campo input per aggiungere prodotti, lista con ng-repeat, pulsante per eliminare ogni prodotto, contatore degli articoli, filtro di ricerca in tempo reale e totale calcolato (ipotizzando un prezzo fisso per ogni prodotto).

πŸ† Esercizio 2 β€” Quiz interattivo

Costruisci un quiz con AngularJS: array di 5 domande con risposta corretta, mostrare una domanda alla volta con ng-show, bottoni per le risposte con ng-click, punteggio aggiornato in tempo reale, schermata finale con risultato e pulsante per ricominciare.

πŸ† Esercizio 3 β€” Dashboard meteo

Crea una dashboard con $http: al caricamento fai un GET a https://wttr.in/?format=j1 o un'API pubblica a tua scelta, mostra temperatura, condizione meteo e icona. Aggiungi un filtro per scegliere l'unitΓ  (Β°C / Β°F) usando un filtro personalizzato AngularJS.

E ora?

Complimenti! Hai completato il corso su AngularJS. Ora conosci le direttive principali, il data binding bidirezionale, i controller, lo scope, i filtri, i servizi, $http, le form con validazione, le animazioni e il routing.

Cosa hai imparato:
  • Direttive fondamentali: ng-app, ng-model, ng-repeat, ng-if, ng-click...
  • Data binding bidirezionale tra Model e View
  • Controller e $scope per la logica dell'applicazione
  • Filtri per formattare e cercare dati
  • Servizi $http per chiamate AJAX
  • Validazione form avanzata con messaggi personalizzati
  • ngAnimate per transizioni CSS automatiche
  • ngRoute per applicazioni Single Page (SPA)

Il passo successivo? Migra verso Angular moderno (v2+) che usa TypeScript, componenti e un'architettura piΓΉ scalabile, oppure esplora altri framework come Vue e React.

Vai al corso Angular β†’Vai al corso JavaScript β†’Torna ai CorsiπŸ“… Prenota una lezione
Provalo tu
Anteprima