Cours de JavaScript - Introduction à Angular

version 1.1.0, dernière mise à jour le 2 décembre 2015.

   

Table des matières (TdM)

  1. I. Généralités
    1. Contexte : les SPA
    2. Patron de conception MVC
      1. Principe
      2. Application à Angular
  1. II. Une application de base
    1. Structure de base : module et contrôleur
    2. Pousser les données vers le DOM : la vue
      1. Exercice : Exercice de base
    3. Binding de données bidirectionnel
      1. Exercice : Exercice de data-binding bidirectionnel
  1. III. Directives
    1. Principe
    2. Appeler une directive dans le DOM
    3. Directives prédéfinies
    4. Définir une nouvelle directive
      1. Exercice : Exercice sur les directives
  1. IV. Filtres
    1. Principe
    2. Filtres prédéfinis
      1. Exercice : Filtres de date
    3. Définir un nouveau filtre
      1. Exercice : Création de filtre
  1. V. Aller plus loin
    1. Les fonctions de scope
      1. Exercice : Ajout de fonctions au scope

Retour au menu

Contenu du cours

I. Généralités

1. Contexte : les SPA

Les Single Page Applications sont des applications Web particulières où l'ensemble des données et leur gestion sont contenus dans une seule et même page. Cela a pour avantage de ne pas avoir à charger de nouvelles pages lors, par exemple, d'une validation de formulaire mais il faut aussi, dans ce cas, que la page soit en mesure de modifier son propre DOM en réponse à des actions de l'utilisateur. Des frameworks JavaScript le permettent, comme Ember, Backbone ou... Angular.

>Retour à la TdM

2. Patron de conception MVC

a. Principe

Un patron de conception, ou design pattern, est un ensemble de bonnes pratiques et de conventions de codage et d'organisation. Un de ces design patterns répandus est le patron «" Modèle-Vue-Contrôleur ». Il permet de concevoir en théorie séparément :

b. Application à Angular

La bibliothèque Angular est structurée autour de quelques concepts-clefs :

Nous allons voir par la suite comment ces structures s'articulent.

>Retour à la TdM

II. Une application de base

1. Structure de base : module et contrôleur

Avant toute chose, il faut télécharger la bibliothèque depuis le site officiel, puis la charger avec par exemple <script src="angular.min.js"></script>. Ce cours est rédigé sur la base d'Angular 1.4.x

Côté JavaScript, on va définir un module, qui ne sera autre que l'application, ainsi que jeter les bases du contrôleur :

var monApp = angular.module("monApp", []) ;

monApp.controller("monControleur", ["$scope", function ($scope){
  //Code du contrôleur...
}]) ;

Côté HTML, on liera l'application et le contrôleur respectivement avec les attributs data-ng-app et data-ng-controller (on peut aussi les écrire ng-app et ng-controller mais cette seconde syntaxe n'est pas valide en HTML5). Par exemple :

<div data-ng-app="monApp">
    <div data-ng-controller="monControleur">
      <!-- Là où seront restituées les données couvertes par le contrôleur -->
    </div>
</div>

C'est par l'intermédiaire de l'objet $scope, dont le nom est prédéfini en Angular, que sera défini le modèle. Il est tout à fait possible de déclarer plusieurs contrôleurs pour un même module :

var monApp = angular.module("monApp", []) ;

monApp.controller("controleurPrincipal", ["$scope", function ($scope){
  //Code du premier contrôleur...
}]) ;
monApp.controller("controleurDonneesUtilisateur", ["$scope", function ($scope){
  //Code du second contrôleur...
}]) ;

>Retour à la TdM

2. Pousser les données vers le DOM : la vue

Il est très facile d'importer dans la vue (le DOM), les données issues du modèle. Par exemple...

<div data-ng-app="monApp">
    <div data-ng-controller="monControleur">
      {{ texte }}
    </div>
</div>

var monApp = angular.module("monApp", []) ;

monApp.controller("controleurPrincipal", ["$scope", function ($scope){
  $scope.texte = "Bonjour!" ;
}]) ;

$scope fait référence à l'élément courant dans le DOM. Cet objet permet la communication entre le DOM et la source de données (statique comme c'est le cas ci-dessus, ou bien dynamique si elles proviennent du serveur). On peut donc y trouver des initialisations de variables comme ici, ou bien des fonctions permettant l'échange de données avec le serveur. Mais en aucun cas ne doivent donc s'y trouver de manipulations du DOM.

Bien évidemment, les données peuvent être plus complexes...

var monApp = angular.module("monApp", []) ;

monApp.controller("controleurPrincipal", ["$scope", function ($scope){
  $scope.utilisateur={} ;
  $scope.utilisateur={
    "prenom" : "Douglas" ,
    "nom" : "Alavanillecilvouplaix" ,
    "dateDeNaissance" : 1995
  } ;
}]) ;

Exercice 1. Exercice de base

Énoncé
Correction

>Retour à la TdM

3. Binding de données bidirectionnel

Angular permet aussi de lier dynamiquement les données modifiées au niveau de la vue, au modèle, et ce sans passer par une étape intermédiaire. On pourra par exemple, sans écrire de contrôleur, directement écrire...

<div data-ng-app="monApp" data-ng-controller="monControleur">
  <p>
    <label for="quantite">Nombre</label>
    <input type="number" id="quantite" data-ng-model="nombre">
  </p>
  <p>Nombre sélectionné : {{ nombre }}</p>
</div>

Ce qui donne...

Exercice 1. Exercice de data-binding bidirectionnel

Énoncé
Correction

>Retour à la TdM

III. Directives

1. Principe

Les directives sont potentiellement complexes, puisque ce sont elles qui permettent de gérer la manière dont les données seront exploitées et restituées à la vue.

>Retour à la TdM

2. Appeler une directive dans le DOM

Il existe quatre manières d'appeler une directive dans le DOM. Nous allons voir comment en créant une directive, nommée nouveau-parag ajoutant un nouveau paragraphe :

L'utilisation en tant qu'attribut est la plus cohérente avec la philosophie et la recommandation de HTML5. On peut d'ailleurs écrire, plus simplement, <p nouveau-parag>Blabla</p> mais cela produit du code invalide.

>Retour à la TdM

3. Directives prédéfinies

La documentation de l'API d'Angular est complète. Nous n'aborderons ici qu'une poignée des directives prédéfinies, afin d'en montrer le principe. Tout d'abord, remarquons que si une directive s'écrit avec un tiret dans le DOM, son nom sera écrit avec des majuscules intercalaires dans le JavaScript :

>Retour à la TdM

4. Définir une nouvelle directive

Enfin, il est possible de définir une nouvelle directive. Reprenons notre exemple initial de directive nouveau-parag. Nous allons définir la nouvelle directive avec la méthode directive, en lui attribuant le nom nouveauParag selon la même convention de transformation des tirets en majuscules. La définition d'une directive renvoie une directive :

monApp..directive('nouveauParag', function(){
  return    {
      template : "<p>Ceci est un nouveau paragraphe.</p>"
    }
}

Dans le HTML, on utilisera la directive ainsi...

<div data-ng-controller="monControleur" data-nouveau-parag> </div>

La méthode directive renvoie un objet directive, constitué des propriétés suivantes :

Exercice 1. Exercice sur les directives

Énoncé
Correction (Correction de la première question)
Correction (Correction de la deuxième question)
Correction (Correction de la troisième question)

>Retour à la TdM

IV. Filtres

1. Principe

Les filtres, comme leur nom l'indique, permettent de préciser le résultat d'une directive, d'une recherche, ou de filtrer la saisie dans un champ de formulaire. Il existe un certain nombre de filtres prédéfinis, mais tout comme pour les directives, il est possible de définir ses propres filtres. La syntaxe générale est de la forme {{ expression | filtre : paramètres du filtre}}

>Retour à la TdM

2. Filtres prédéfinis

Là encore, la documentation officielle d'Angular donne de nombreux exemples. Voici quelques filtres utiles, mais il y en a d'autres :

Exercice 1. Filtres de date

Énoncé
Correction

>Retour à la TdM

3. Définir un nouveau filtre

Angular permet la création de nouveaux filtres avec la méthode filter. Par exemple...

monApp.filter("permute", function(){
  return function(entree)  {
  var sortie = '' ;

  for (var i=0;i<entree.length;i++)    {
    switch(entree[i])      {
        case 'a': sortie+='e';break ;
        case 'e': sortie+='i';break ;
        case 'i': sortie+='o';break ;
        case 'o': sortie+='u';break ;
        case 'u': sortie+='y';break ;
        case 'y': sortie+='a';break ;
        defaultsortie+=entree.charAt(i) ;
      }
    }
  return sortie ;
  }
}) ;

<div data-ng-controller="monControleur" data-ng-init="chaine='Texte n\'ayant pas de sens mais y a-t-il besoin d\'en avoir un?'">
  <p>Sans filtre&nbsp;: {{chaine}}</p>
  <p>Avec filtre&nbsp;: {{chaine | permute}}</p>
</div>

Exercice 1. Création de filtre

Énoncé
Correction

>Retour à la TdM

V. Aller plus loin

1. Les fonctions de scope

Les fonctions de scope permettent, dans le contrôleur, de changer les données du modèle. Il s'agit bien ici de modifier les données, mais en aucun cas de modifier le DOM.

var monApp = angular.module("monApp", []) ;

monApp.controller("monControleur", ["$scope", function ($scope){
  $scope.supprime = function (index)
    {
      $scope.liste.splice(index, 1) ;
    }
}]) ;

<div data-ng-controller="monControleur" data-ng-init="liste=[{'nom':'Vaistairstalone', 'prenom':'Cécile'},{'nom':'Danlavoiturpourpassalir', 'prenom':'Amadeus'},{'nom':'Zeblouze','prenom':'Agathe'},{'nom':'Binuneptitsieste', 'prenom':'Geoffrey'}]">
  <ul>
    <li data-ng-repeat="personne in liste" data-ng-click="supprime($index);">{{personne.prenom}} {{personne.nom}}</li>
  </ul>
</div>

Dans le code précédent, Angular se charge de reconnaître quel élément il convient de supprimer à l'aide de la variable $index

Exercice 1. Ajout de fonctions au scope

Énoncé
Correction

>Retour à la TdM

Historique de ce document

Conditions d'utilisation et licence

Creative Commons License
Cette création est mise à disposition par Gilles Chagnon sous un contrat Creative Commons.

Retour au menu