angular-logo
AngularJS

Bien démarrer avec AngularJS

Le développement avec AngularJS peut être très différent du développement avec du pur JavaScript, ou jQuery, voire même avec d’autres frameworks ou librairies comme BackbonsJS. AngularJS offre tellement de choses aux développeurs, mais requiert en échange une nouvelle façon de penser (vos applications Web).

Croyez-moi, cela vaut la peine.

Si vous apprenez à penser comme AngularJS, non seulement vous serez plus productifs, mais votre code serait plus simple à écrire, plus expressif et vous aurez moins de difficultés à tester et déboguer votre application.

Adoptez la philosophie d’AngularJS…

Pour décrire la philosophie d’AngularJS, je dirais qu’il crée “une liaison entre un état et une vue, le tout de façon déclarative” (mais pas que!). Je m’explique :

Par “état” je veux parler de toutes les données stockées en mémoire et nécessaires au bon fonctionnement de votre application. Et par “vue” je veux parler du contenu visible à l’utilisateur, autrement-dit le DOM.

Maintenant, qu’est-ce que j’entend par “une liaison créée de façon déclarative” ? Tout d’abord, par “déclarative” je veux surtout dire “non impérative”. Nous savons tous ce que c’est un code impératif : c’est une succession d’instructions qui change l’état de l’application.  Prenons par exemple le code jQuery suivant :

var el, i;
for (i = 0; i < users.length; i++) {
    el = $('<li>');
    el.innerHTML = users[i].name;
    $('.users').append(el);
}

Ce code est donc un code impératif puisque nous avons une séquence d’instructions qui créent et modifient des objets, ainsi que le DOM. Nous créons un nouvel élément HTML <li> et nous l’affectons à la variable el, nous modifions la propriétés innerHTML de cet élément puis nous l’insérons dans le DOM. Chaque itération modifie le contexte d’exécution.

Voici maintenant ce que propose AngularJS :

<li data-ng-repeat="user in users">{{user.name}}</li>

Que ce passe-t-il dans ce bout de code ? Nous avons déclaré un élément HTML <li> et nous lui avons ajouté un attribut personnalisé data-ng-repeat. Avec cet attribut nous indiquons au compilateur de template d’AngularJS que nous voulons toujours un élément <li> pour chaque user de notre liste de users. Nous avons également référencé le user de cet élément <li> entre doubles accolades. Cette syntaxe demande au compilateur d’AngularJS de créer une relation entre cette partie du DOM et l’attribut name de l’objet user.

Ceci nous ramène à ce que je disais plus haut “une liaison entre un état et une vue”. Dans cet exemple, cette liaison (représentée par les accolades) traduit l’affectation faite par el.innerHTML = users[i].name. AngularJS possède donc cette liaison uni-directionnelle qui ressemble plus au moins à une affectation impérative, qui est en soit une opération au sens mathématique ; toutes modifications ultérieures apportées à users[i].name n’aura aucun effet sur cette opération. Cependant, grâce à cette liaison, cette partie du DOM (la vue) sera automatiquement mise à jour pour refléter la valeur (ou l’état) de l’attribut name.

Ce qui est intéressant aussi avec AngularJS, est que dans l’exemple plus haut, nous avons deux liaisons (uni-directionnelles) de créées. Celle créée par les doubles accolades dont nous venons de parler. Mais la première a été créée par l’attribut data-ng-repeat. Que cela signifie-t-il pour nous développeurs ? Tout simplement, un gain de temps, puisque AngularJS va s’assurer de mettre à jour le DOM à chaque fois que l’objet users a été modifié (ajout ou suppression d’entrées).

AngularJS propose également une liaison bi-directionnelle où les modifications se propagent de l’état vers le DOM, mais également de la vue vers l’état de l’application, suite à l’interaction avec l’utilisateur. Voici un exemple très simplifié  de cette liaison bi-directionnelle (accéder au plnkr de cet exemple) :

<body ng-app ng-init="users = [{name:'Douglas Crockford'}, {name:'Paul Iris'}]">
  <button type="button" ng-click="users.push({name:'Wassim Chegham'});">
    Add user
  </button>
  <ul>
    <li ng-repeat="user in users track by $index">
      {{$index}} - {{user.name}}
    </li>
  </ul>
</body>

Dans cet exemple, nous initialisons un modèle users contenant deux entrées. Au lancement de la page, nous voyons que le DOM affiche bien ces deux entrées. Maintenant, si nous cliquons sur le bouton, celui-ci permet d’ajouter une nouvelle entrée au tableau users. A chaque mise à jour de ce tableau, le DOM est également mis à jour en affichant toujours toutes les entrées du modèle. Grâce donc à AngularJS nous avons crée une liaison bi-directionnelle entre le DOM et le modèle users. Imaginons que nous recevons un message du serveur qui vient modifie le modèle users, grâce à cette liaison, le DOM restera toujours synchronisé au modèle.

Bon, il est clair qu’AngularJS n’est pas simplement un framework JavaScript 100% déclaratif. Vous aurez besoin d’écrire du code impératif, beaucoup de code, qui va forcement modifier l’état de votre application. Mais en utilisant AngularJS, vous économiserez des centaines de lignes de code (cela dépend de la taille de votre application) que vous aurez codé juste pour garder tous vos modèles et vos vues synchronisés.

Pensez comme AngularJS…

Quand j’ai commencé à coder avec AngularJS, je n’ai pas vraiment eu de problème à mettre en pratique ce que j’avais lu dans la documentation (quand celle-ci était à jour!) ou ce que je lisais dans le code source. Pour les débutants, AngularJS reste quand même simple et intuitif.  Cependant, dès lors que j’ai commencé à utiliser des API avancées comme les directives ou intégrer des librairies externes, les problèmes ont commencé et j’avais du mal à écrire du code “propre” qui soit bien interprété par AngularJS (ou plutôt son compilateur). Il m’a fallu un moment avant de comprendre que ce que je faisais n’était pas bon. Je ne pensais pas (encore) comme AngularJS. Je devais arrêter d’écrire du code impérative (ou le moins possible) et me déclarer des liaisons (je vulgarise bien évidement).

Il y a beaucoup de concepts dont je n’ai pas vraiment parlé dans ce billet, qui nous permettent d’écrire du code déclaratif, entre autres : les directives personnalisées, le systèmes du $watch d’AngularJS ainsi que le module $ngModel. Apprendre à écrire du code déclaratif implique l’utilisation de tous ces principes et concepts. Voici une compilation de trucs et astuces que j’ai appris au fil des jours et qui vous seront peut être utiles :

  • Utilisez $ngModel pour créer des liaisons bi-directionnelles dans vos directives ;
  • Evitez le plus possible les évènements et privilégiez les systèmes de $watch et ng-change proposés par AngularJS qui s’occuperons de synchroniser vos modèles et vos vues ;
  • N’abusez pas trop des $watch quand même ;
  • Si vous devez utiliser l’API Event, $on(), $emit() et $broadcast(), privilégiez le couple $on()/$emit() car plus performant ;
  • Evitez le plus possible d’écrire du code impératif qui modifie le DOM. Passez par des directives ;
  • Mettez dans les directives tout le code nécessaire qui interagit avec des librairies externes. Mettez ce code dans les fonction link ou compile ;
  • Si vous offrez un support pour IE, déclarez toujours vos directives en tant qu’attributs ;
  • Utilisez des services pour partager vos états entre les contrôleurs ;
  • Evitez d’utiliser le $rootScope, c’est comme si vous utilisiez l’objet window en JavaScript.

Pour finir, développer avec AngularJS peut vous sembler différent des autres frameworks, c’est vrai. Mais si vous accordez un peu de votre temps à apprendre à penser comme AngularJS, et produire du code qui respecte la philosophie d’AngularJS, vous serez alors récompensé et tout le monde sera content, vous ainsi que vos chefs ^^

Standard
  • http://groupe-sii.fr Igor Rosenberg

    On pourra suivre particulièrement Thierry Chatel (@ThierryChatel) sur le sujet angularJS. Il a présenté très récemment à Rennes ce sujet, voir https://github.com/tchatel/last-tweets-angularjs/ (démonstration de la fcailité d’utilisation) et aussi https://github.com/tchatel/slides-jug-bretagne (pour des infos de plus haut niveau)

  • L Nico

    C’est amusant, ça ressemble furieusement au binding proposé par .net depuis WPF.

    C’est intéressant de voir ce genre de philosophie se généraliser.

    • http://ng.cheghamwassim.com Wassim Chegham

      Tu trouveras ce concept de Data Binding dans pas mal de langages. Je penses notamment à Java et JFace, Flex et MXML ou encore C#/VB/C++ et XAML.

      En JavaScript, le concept de Data Binding est apparu avec Ember.js et KnockoutJS qui proposaient deux approches différentes, mais AngularJS propose, lui, une autre facon de faire, inspirée bien évidement des deux lib mais de façon très simple…

      • L Nico

        “Tu trouveras ce concept de Data Binding dans pas mal de langages. Je penses notamment à Java et JFace, Flex et MXML ou encore C#/VB/C++ et XAML.”

        => Oui, c’est ce que je dis. “WPF” étant le résultat de l’association entre les langages .net (C#/VB.net/C++_CLI/J#…) et la syntaxe XAML.

        Ce n’est évidemment pas le seul exemple de framework bindable, mais c’est l’un des plus connus pour les développeurs applicatifs. En l’occurrence, celui-ci remonte à 2006 (je ne sais pas pour les autres).

  • Pingback: AngularJS : intégrer des Web Workers | Blog technique SII Ouest()

  • Pingback: A blog for developers …()

  • Pingback: AngularJS : intégrer des Web Workers | Learn, Think, Create…()