Passaggio all'ora legale 31 marzo 2024 02:00 03:00 sposta avanti l'orologio di 1 ora (si dorme 1 ora in meno)
AngularJS 1 è, similmente a Knockout JS, un framework JavaScript per implementare il pattern Model-View-View Model (MVVM) lato client, ma non si limita solo a questo, infatti va oltre e permette di gestire intere applicazioni basate su una sola pagina dette Single Page Application (SPA). In aggiunta, non richiede l'uso di un modello basato su oggetti specifici (observable) come Knockout JS, quindi è più semplice da gestire.

Per utilizzarlo è necessario avere la libreria JavaScript AngularJS 1, negli esempi seguenti uso anche il CSS di Bootstrap 3 per semplificare il disegno della UI.
Tutti gli esempi sono basati sulla versione 1 di AngularJS

In pratica, tramite Angular, posso decorare l'html tramite degli attibuti e agganciarlo al modello JavaScript in modo tale che ogni modifica fatta al modello si rifletta sulla pagina html e viceversa. Ovvero una modifica fatta sulla pagina html, ad esempio l'iserimento di un valore in una textbox sia direttamente salvato su una variabile del modello JavaScript. Quello che avviene è un binding bidirezionale tra il modello (Model) JavaScript e la rappresentazione html (View).

Quello che segue è un semplice esempio che prende in input due numeri e li somma mostrando il risultato a video. Inoltre in caso di risultato negativo, lo evidenzia con uno sfondo rosso.


Questa app è realizzata con questo codice (Test 1):
HTML
<!DOCTYPE html>
<!-- dichiaro il nome della app da usare nel javascript -->
<html ng-app="sgartApp">

<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Test 1</title>
  <link href="/models/css/bootstrap.min.css" rel="stylesheet">
</head>

<body>

  <div class="container">
      <h2>Test 1 <small>AngularJS 1</small></h2>
  </div>

  <div class="container">
    <!-- inizializzo le variabili n1 e n2 -->
    <form class="form-horizontal" ng-init="n1=5;n2=7">
      <div class="form-group">
        <label class="col-sm-2 control-label">Numero 1</label>
        <div class="col-sm-10">
          <!-- uso ng-model per fare il binding bidirezionale -->
          <input type="number" class="form-control" ng-model="n1">
        </div>
      </div>
      <div class="form-group">
        <label class="col-sm-2 control-label">Numero 2</label>
        <div class="col-sm-10">
          <input type="number" class="form-control" ng-model="n2">
        </div>
      </div>
      <div class="form-group">
        <label class="col-sm-2 control-label">Totale</label>
        <!-- uso ng-class per cambiare il colore di sfondo quando il risultato è negativo -->
        <label class="col-sm-10" ng-class="{'bg-danger': n1 + n2 < 0}">
          <!-- uso ng-bind per fare il binding unidirezionale, posso usare delle espressioni -->
          <span ng-bind="n1 + n2"></span>
      </div>
  </div>

  </form>
  </div>

  <script src="/models/angular.min.js"></script>
  <script type="text/javascript">
  (function(){  // richiudo tutto in una enclosure per evitare conflitti di nomi
	   "use strict";
     
     //inizializzo angular
	   angular.module("sgartApp", []);
	})();
  </script>
</body>

</html>
Gli elementi da tenere presente per un app Angular sono:
  • deve esserci un attributo ng-app con il nome dell'applicazione
  • deve esserci del codice JavaScript che dichiara e inizializza la app: angular.module('sgartApp', []);
  • uso l'attributo ng-init per inizializzare le variabile (vengono create implicitamente da angular delle variabili JavaScript e inizializzate nello scope)
  • uso l'attributo ng-model quando devo attivare il binding bidirezionale tra la view e il model (controlli di input)
  • uso l'attributo ng-bind quando devo attivare il binding unidirezionale tra il model e la view (solo visualizzazione, posso usare delle espressioni)
  • uso l'attributo ng-class per applicare una classe css in base al risultato true/false di una espressione

Usato in questo modo non esprime tutte le potenzialità, l'ideale è avere un controller in modo da separare il model dalla view, quindi il codice diventa (Test 2):
JavaScript
(function(){  // richiudo tutto in una enclosure per evitare conflitti di nomi
  "use strict";
     
  // inizializzo angular
  var app = angular.module("sgartApp", []);
     
  // creo un CONTROLLER
  // la variabile $scope viene "iniettata" (inject) da angular
  app.controller("TestCtrl", function($scope) {
    // dichiaro le varibili e le aggancio allo scope
    $scope.n1 = 5;
    $scope.n2 = 7;
      
    // dichiaro le funzioni e le aggancio allo scope	
    $scope.somma = function() {
      return $scope.n1 + $scope.n2;
    };
      
    $scope.isNegative = function(){
      return $scope.somma() < 0;
    };
      	
  });
})();
le variabili che iniziano con dollaro ($) sono variabili di AnguarJS
per utilizzarlo devo dichiarare nella view il controller tramite l'attributo ng-controller e sotituire le espressioni, che prima erano in linea nell'html, con le relative funzioni:
HTML
<!-- tramite ng-controller dichiaro quale controller deternina lo scope delle variabili -->
  <div class="container" ng-controller="TestCtrl">
    <form class="form-horizontal">
      <div class="form-group">
        <label class="col-sm-2 control-label">Numero 1</label>
        <div class="col-sm-10">
          <!-- uso ng-model per fare il binding bidirezionale -->
          <input type="number" class="form-control" ng-model="n1">
        </div>
      </div>
      <div class="form-group">
        <label class="col-sm-2 control-label">Numero 2</label>
        <div class="col-sm-10">
          <input type="number" class="form-control" ng-model="n2">
        </div>
      </div>
      <div class="form-group">
        <label class="col-sm-2 control-label">Totale</label>
        <!-- uso ng-class per cambiare il colore di sfondo quando il risultato è negativo richiamando una funzione -->
        <label class="col-sm-10" ng-class="{'bg-danger': isNegative()}">
          <!-- uso ng-bind per fare il binding unidirezionale -->
          <span ng-bind="somma()"></span>
        </label>
      </div>
  </div>

In questo caso le variabili si riferiscno allo scope delimitato dal tag html su cui ho applicato l'attributo ng-controller. In caso di più controller annidati serve un meccanismo per identificare la variabili di uno specifico controller rispetto ad un altro, devo assegnare un alias al controller che userò nel Model.
A questo punto il codice diventa (Test 3):
JavaScript
(function(){  // richiudo tutto in una enclosure per evitare conflitti di nomi
  "use strict";
 
  // inizializzo angular
  var app = angular.module("sgartApp", []);
})();
 
(function(){  //dichiaro un altra enclosure per simulare che esista su un altro file, meglio avere un file per controller
  "use strict";
 
  console.log(typeof app); // la variabile app non esiste -> undefined
 
  // se il controller è in un altro file non ho la variabile app riprendo la app tramite angular.module("sgartApp")
  angular.module("sgartApp").controller("TestCtrl", TestCtrl);  // per leggibilità non dichiaro direttamente la funzione ma solo il nome

  // dichiaro le variabili di cui voglio fare l'inject ($scope e $http non è usato in questo caso solo come esempio)
  TestCtrl.$inject = ["$scope", "$http"];

  function TestCtrl($scope, $http) {
    var self = this; // memorizzo l'oggetto controller
	
    // dichiaro le varibili e le aggancio al controller 
    self.n1 = 5;
    self.n2 = 7;
	
    // dichiaro le funioni e le aggancio al controller	
    self.somma = function() {
      return self.n1 + self.n2;
    };
	
    self.isNegative = function(){
      return self.somma() < 0;
    };
		
  }
})();
la principale differenza è che non "aggancio" più le variabili allo $scope ma direttamente al controller this.
Questo mi permette di definire un alias nella view (ctrl):
HTML
<!-- tramite ng-controller dichiaro il controller 
  non avendo usato $scope devo dichiarare un alias, ad esempio, 'ctrl'  -->
<div class="container" ng-controller="TestCtrl as ctrl">
  <form class="form-horizontal">
    <div class="form-group">
      <label class="col-sm-2 control-label">Numero 1</label>
      <div class="col-sm-10">
        <!-- uso ng-model per fare il binding bidirezionale 
              avendo un alias le variabili vanno referenziate con l'alias -->
        <input type="number" class="form-control" ng-model="ctrl.n1">
      </div>
    </div>
    <div class="form-group">
      <label class="col-sm-2 control-label">Numero 2</label>
      <div class="col-sm-10">
        <input type="number" class="form-control" ng-model="ctrl.n2">
      </div>
    </div>
    <div class="form-group">
      <label class="col-sm-2 control-label">Totale</label>
      <!-- uso ng-class per cambiare il colore di sfondo quando il risultato è negativo richiamando una funzione -->
      <label class="col-sm-10" ng-class="{'bg-danger': ctrl.isNegative()}">
        <!-- uso ng-bind per fare il binding unidirezionale -->
        <span ng-bind="ctrl.somma()"></span>
      </label>
   </div>
</div>

Questo è solo un esempio che usa un sotto insieme degli attributi disponibili e delle potenzialità del framework AngulaJS 1.
Potrebbe interessarti anche: