Présentation AngularJS

Jean Detoeuf

Sommaire

  • Introduction et besoin
  • Utilisation basique d'AngularJS
  • Tests unitaires
  • Composants d'AngularJS
  • Création de composants

Jean Detoeuf

  • Ingénieur concepteur/développeur
  • Passionné de Java, Spring, Web, Javascript
  • Adore plein de choses hype comme le growth hacking, nodeJS, la programmation reactive, fonctionnelle, le continuous delivery, sauter dans le vide et les choses qui vont vite
  • Aime la bière, les voyages, le roller, courir
  • Et les nouvelles technos en général

Sondage

Qui

  • A déjà utilisé JavaScript ?
  • A déjà utilisé jQuery ?
  • A déjà utilisé un autre framework JavaScript ?
  • A déjà entendu parler d'AngularJS ?
  • A déjà utilisé AngularJS ?
  • Est à l'aise avec AngularJS ?

Intro

Besoin

  • Fonctionnement standard client/serveur avant 2005 : le serveur produit une page, le client en fait le rendu
  • 2005 : Arrivée d'AJAX
  • Des "bouts" de page peuvent être affichés à la demande : il n'est pas nécessaire de recharger une page à chaque action
  • Aucune intelligence réelle côté client

Evolution des interfaces web

Pourquoi on n'avait pas fait comme ça avant ?

  • JavaScript existe depuis longtemps
  • L'évolution de la puissance des terminaux (PC, mobile) permet de placer de l'intelligence côté client.
  • Les moteurs JavaScript se sont améliorés à partir de 2008 (merci AJAX).
  • Même les mobiles peuvent tirer parti de cette amélioration
AngularJS
  • Framework JS développé par Google
  • Première version 2009
  • Fondé sur la programmation déclarative
  • Architecture MVC ou plutôt MVVM
  • Injection de dépendance

Pourquoi apprendre un framework JavaScript ?

  • Vers un monde d'API
  • Applications riches
  • Applications pour mobiles et tablettes avec PhoneGap
  • Présenter des données d'une manière plus simple et efficace
  • Intelligence "rapide" côté serveur avec Node.js

Points forts

  • Open Source
  • Maintenu par Google
  • Injection de dépendance
  • Couplage faible entre présentation, données, composants métier
  • Tests unitaires et bout en bout
  • Compatible REST
  • Compatible WebSockets

Points faibles

  • Encore en évolution
  • Ne fonctionne pas sur IE6, et adaptations à faire pour IE7 et IE8
  • La gestion des fichiers peut vite devenir cahotique si on ne la maitrise pas.
  • Validation à implémenter côté client
  • Possibilité d'être remplacé un jour par DartJS

Concurrents

  • Backbone.js
  • Ember.js
  • Knockout.js
  • React.js
  • Plusieurs frameworks qui gèrent le rendu HTML, les feuilles de style, voir même le Back Office
  • JQuery n'est pas un concurrent, il est complémentaire
  • La force d'AngularJS est de ne pas tout faire, de se concentrer sur le MVVM

Pourquoi AngularJS plutôt qu'un autre framework JavaScript ?

(Moi j'adore le jQuery, ça marche très bien...)

Concurrents

Utilisation d'AngularJS

Bases

Installation

  • Aller sur angularjs.org
  • Télécharger la dernière version et l'inclure dans sa page web
  • Ou utiliser le CDN Google pour l'inclure dans sa page web
<html ng-app="myApp">
<head>
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.16/angular.min.js"></script>
</head>
<body>
</body>
</html>

Evaluations

  • Une évaluation permet d'afficher une valeur
  • Exemple : {{1+1}} affiche 2
<html ng-app="myApp">
<head>
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.16/angular.min.js"></script>
  <script type="text/javascript">
  var myApp = angular.module('myApp', []);
  </script>
</head>
<body>
	Réponse : {{ 7 * 6 }}
</body>
</html>

Démonstration

Injection de dépendances 1/2

  • Permet l'inversion de contrôle
  • Fonctionne par module
  • Un module peut dépendre d'autres modules
  • Il est alors possible de faire appel aux méthodes de ces modules
  • Permet la séparation de considérations
  • Code testable unitairement (un module représente une fonctionnalité et les autres modules peuvent être mockés)

Injection de dépendances 2/2

  • L'injection se fait simplement en l'ajoutant à la liste des dépendances du module
  • Puis le module peut être utilisé en paramètre d'une fonction
angular.module('myApp', ['Clock','Bell']);
var ringMyBell = function($scope,Clock,Bell){...}

controleur

  • Conteneur permettant de gérer des variables
  • En JavaScript, des variables peuvent être des fonctions
  • Les variables d'un controleur sont contenue dans son $scope
  • Le $scope permet l'étanchéité des variables au sein du controleur
<html ng-app="myApp">
<head>
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.16/angular.min.js"></script>
  <script type="text/javascript">
  var myApp = angular.module('myApp', []);
  myApp.controller('MyCtrl', function MyCtrl($scope) {
    $scope.reponse = 42;
  });
  </script>
</head>
<body ng-controller="MyCtrl">
  Réponse : {{ reponse }}
</body>
</html>

Démonstration

Répéteur

  • ng-repeat permet d'itérer sur une liste (ie. foreach)
<html ng-app="myApp">
<head>
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.16/angular.min.js"></script>
  <script type="text/javascript">
  var myApp = angular.module('myApp', []);
  myApp.controller('MyCtrl', function MyCtrl($scope) {
    $scope.elems = [0,1,1,2,3,5,8,13];
  });
  </script>
</head>
<body ng-controller="MyCtrl">
  {{elems.length}} premiers éléments de la suite de Fibonacci :
  <ul><li ng-repeat="elem in elems track by $index">{{elem}}</li></ul>
</body>
</html>

Démonstration

Filtres 1/3

  • Permet de modifier le rendu d'une valeur
  • Peut s'appliquer sur des listes
  • Exemple de filtres :
    • filter
    • orderBy
    • limitTo
    • date
    • currency
    • json
    • lowercase
    • uppercase
    • number

Filtres 2/3

<html ng-app="myApp">
<head>
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.16/angular.min.js"></script>
  <script type="text/javascript">
  var myApp = angular.module('myApp', []);
  myApp.controller('MyCtrl', function MyCtrl($scope) {
    $scope.technos = ['JavaScript', 'HTML', 'CSS', 'Java'];
  });
  </script>
</head>
<body ng-controller="MyCtrl">
  Technologies :
  <ul><li ng-repeat="techno in technos">{{techno}}</li></ul>
  Technologies Java* :
  <ul><li ng-repeat="techno in technos | filter:'Java'">{{techno}}</li></ul>
</body>
</html>

Démonstration

Filtres 3/3

  • Possibilité de créer ses propres filtres
  • Permet de factoriser un comportement
<html ng-app="myApp">
<head>
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.16/angular.min.js"></script>
  <script type="text/javascript">
    var myApp = angular.module('myApp', []).filter('truncate', function () {
        return function (text,length) {
            return (text.length<=length)?text:(String(text).substring(0,length)+'...');
        };
    });
    myApp.controller('MyCtrl', function MyCtrl($scope) {
        $scope.blah = 'blah blah blah blah blah blah blah blah blah';
    });
  </script>
</head>
<body ng-controller="MyCtrl">
	<table>
		<tr><td>Avant filtre</td><td>{{blah}}<td/></tr>
		<tr><td>Après filtre de taille 18</td><td>{{blah|truncate:18}}<td/></tr>
	</table>
</body>
</html>

Démonstration

Binding bidirectionnel 1/3

  • Vue vers Modèle : Certains composants permettent de modifier le modèle à partir de la vue
  • Modèle vers Vue : Toute modification du modèle entraine la modification de la vue associée
  • AngularJS est assez intelligent pour savoir quels sont les composants affectés par une modification
  • Chaque mise à jour de la vue à partir du modèle s'appelle un digest
  • AngularJS optimise le digest pour le rendre très perfomant, voir instantané

Binding bidirectionnel 2/3

Binding bidirectionnel 3/3

<html ng-app="myApp">
<head>
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.16/angular.min.js"></script>
  <script type="text/javascript">
  var myApp = angular.module('myApp', []);
  myApp.controller('MyCtrl', function MyCtrl($scope) {
    $scope.nom = 'le monde';
  });
  </script>
</head>
<body ng-controller="MyCtrl">
  Bonjour <input ng-model="nom"/><br/>
  Comment ça va, {{nom}} ?
</body>
</html>

Démonstration

Ressources

  • Angular gère nativement le REST
  • Il est possible d'effectuer n'importe quelle requête HTTP
  • Définir une vraie ressource HTTP avec paramétrage de l'URI (ie. /user/:id ou /post/:name)
  • <html ng-app="myApp">
    <head>
      <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.16/angular.min.js"></script>
      <script type="text/javascript">
    var myApp = angular.module('myApp', ['ngResource']);
    myApp.factory('AngularJsIssues', function($resource){
      return $resource('https://api.github.com/repos/angular/angular.js/issues');
    });
    myApp.controller('MyCtrl', function MyCtrl($scope,AngularJsIssues) {
      $scope.issues = AngularJsIssues.query();
    });
      </script>
    </head>
    <body ng-controller="MyCtrl">
      <table>
        <tr>
          <th>Id</th>
          <th>State</th>
          <th>Title</th>
        </tr>
        <tr ng-repeat="issue in issues">
          <td ng-bind="issue.id"></td>
          <td ng-bind="issue.state"></td>
          <td ng-bind="issue.title"></td>
        </tr>
      </table>
    </body>
    </html>

Démonstration

Utilisation d'AngularJS

Tests

Introduction

  • Quoi ? des tests automatisés en JavaScript ??
  • Tests unitaires et tests bout en bout (E2E)
  • Lancement des tests avec
  • Les tests peuvent être lancés sur plusieurs navigateurs
  • Karma peut aussi faire les tests sur un port (ie. mobile ouvert sur un port d'écoute)

Exemple

  • Unit tests : Test d'un module
  • End-to-end tests : Test de plusieurs modules
  • Les interfaces peuvent être bouchonnées (voir angular.mock.inject)
  • Tous les exemples de cette présentation ont leur test
'use strict';
describe('myApp', function(){
  var curModule;
  beforeEach(curModule = module('myApp'));
  describe('myApp module', function(){
    it('should have a module', function() {
      expect(curModule).not.toBeNull();
    });
  });
  describe('Controller', function(){
    var scope, ctrl;
    beforeEach(inject(function($rootScope, $controller) {
      scope = $rootScope.$new();
      ctrl = $controller('MyCtrl', {$scope: scope});
    }));
    it('should have a controller', function() {
      expect(ctrl).not.toBeNull();
    });
  });
});

Utilisation d'AngularJS

Fonctions avancées

Directives 1/2

  • Utiliser des nouveaux tags
  • Utiliser des nouveaux attributs
  • <alert>Alerte !</alert>
    <datepicker min="minDate" show-weeks="showWeeks"/>
    		

Directives 2/2

  • Possibilité de créer ses directives
  • Comme si on réécrivait du HTML
  • Peut être "compilé"
  • <twitter-tweet-page/>
    <google-plus-page/>
    <facebook-like-page/>
    <twitter-direct-message user="@thebignet"/>
    <twitter-followers user="@thebignet"/>
    <github-last-commit user="thebignet" project="pres-angularjs"/>
    		

router

  • Permet de lier à une URI une vue et un controleur
  • /users affiche la vue imbriquée users.html avec le controleur UserCtrl

ui-router

  • Meilleur que le routeur intégré à AngularJS
  • Permet de gérer des états plutôt que des URI
  • Plusieurs vues/controleurs pour un URI
  • Vues imbriquées
  • Directive pour une navigation plus simple

Vues

  • Avec le routeur intégré à AngularJS
myApp.config(['$routeProvider',
function($routeProvider) {
  $routeProvider
    .when('/users', { templateUrl: 'users.html', controller: 'UserCtrl' })
    .otherwise({ redirectTo: '/' });
}]);
<div ng-view></div>

Vues

  • Avec ui-router
myApp.config(function($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise("/");
$stateProvider.state('users', { url: "/users", templateUrl: "users.html" })
});
<div ui-view></div>

Animations

  • Basé sur des évènements liés à des directives
  • Suite à l'ajout/suppression d'un élément à une liste
  • Suite à la modification d'une valeur
  • AngularJS applique des classes CSS spécifique avant et pendant l'action
  • Toutes les transitions CSS3 sont utilisables

jQuery

  • Version allégée de jQuery inclue dans AngularJS
  • Peut être surchargée par la version complète
  • La version allégée ne contient pas les sélecteur css et c'est pour votre bien car ce n'est pas la philosophie d'AngularJS

Bons amis d'AngularJS

Grunt Bower Yeoman

Intégration continue

  • Les tests peuvent être exécutés sur plusieurs navigateurs à chaque sauvegarde en local ou à chaque commit
  • Karma peut être lancé par Jenkins, Sonar, ou Travis
  • Les rapports produits sont au format Junit
Travis Jenkins Sonar

Pour monter un projet rapidement

  • Angular-seed
  • Framework CSS : Twitter Bootstrap, Foundation
  • Utiliser Yeoman avec generator-angular ou generator-jhipster

Hébergement

  • Le serveur peut héberger les ressources front et fournir l'API
  • Possibilité d'avoir un serveur statique pour le front et une API pour le back
  • Plus de flexibilité quant à la charge reposant sur chacun
  • Les serveurs frontaux peuvent mettre les ressources en cache efficacement
  • Les serveurs d'API peuvent être dimensionnés
  • Ce découpage se prête plus facilement à un cloud

Questions ?

Remerciements

Merci !