Welcome !
I have nothing to o튵䎣er but blood, toil, tears, and
sweat.
W. Churchill, 13 mai 1940
@pierrci
Evolution of Web Apps
https://evolution-of-apps.剭녲rebaseapp.com
David East - Firebase & Angular team
So... Angular !
En 4 mots clés
Framework Javascript
SPA
(o_O)
Google
MVW
Au sujet de MVC / MVVM :
http://www.docdoku.com/blog/2015/02/17/architecturer-ses-applications-js-pattern-mvvm/
http://stackover�ow.com/questions/667781/what-is-the-di튵䎣erence-between-mvc-and-mvvm/
Aujourd'hui, version 1.X - https://angularjs.org/
Demain, version 2.X - https://angular.io/
-
AngularJS however is not an example of developers
maintaining backwards compatibility. It takes
pleasure in starting over. In fact, you can just
about rip up your old Angular apps now. It’s for
your own good.
@EdwardCGordon packtpub.com
La classe non ?
Ready for roller coasters ?
Sans Angular...
<html> 
    <head>
        <title>Index</title> 
    </head> 
    <body>
        Name: <input type="text" id="myInputBox"> 
        Hello <span id="nameSpan"></span> !             
        <script>
</script> 
    </body> 
</html>
 
            var inputElem = document.getElementById("myInputBox"); 
            inputElem.addEventListener('keyup', function() { 
                var text = inputElem.value; 
                document.getElementById("nameSpan").innerHTML = text; 
            }); 
        
Avec Angular !
<html> 
    <head>
        <title>Index</title> 
        <script src="../angular.min.js"></script> 
    </head> 
    <body ng­app> 
        Name: <input type="text" ng­model="nameModel"> 
        Hello {{ nameModel }} ! 
    </body> 
</html>
<html> 
    <head> 
        <title>Index</title> 
        <script src="../angular.min.js"></script> 
    </head> 
    <body ng­app> 
        Name: <input type="text" ng­model="nameModel"> 
        Hello {{ nameModel }} ! 
    </body> 
</html>
ng-app : directive de bootstrap ("démarrage"), indique à angular
où se situe l'application dans la page HTML.
ng-model : directive qui associe ("bind") la valeur d'un champ à
une variable.
{{ nameModel }} : expression angular, elle est évaluée par angular
et son résultat est inséré dans la page.
<demo />
Les modules
<body ng­app="monApplicationAngular">
La valeur passée à ngApp est le nom du module principal de
l'application.
Un module contient les composants de notre application :
controllers, directives, services, 剭녲ltres...
Pour pouvoir ajouter ces composants, il faut déclarer le module côté
javascript :
var app = angular.module("monApplicationAngular", [ 
    "ngRoute", 
    "ngResource", 
    //... 
]); 
// Dans sa forme la plus simple : 
// var app = angular.module("monApplicationAngular", []);
Une fois déclaré, on peut l'appeler et lier des composants :
angular 
    .module("monApplicationAngular") 
    .directive("uneDirective", maDirective); 
     
function maDirective() { 
    //... 
}
Les expressions Angular
<body ng­app="monApplicationAngular"> 
    1 + 2 = {{ 1 + 2 }} 
    Nom de l'utilisateur : {{ user.name }} 
    Loisir n° 3 de l'utilisateur : {{ user.loisirs[2] }} 
</body>
Comment et où déclarer user ?
=> Dans un controller
Les controllers
C'est là que l'on interagit avec les données de la vue
angular 
    .module("monApplicationAngular") 
    .controller("HomeController", HomeController); 
function HomeController() { 
    var vm = this; // vm pour ViewModel 
    vm.user = { 
        name: "Pierric", 
        loisirs: ['ski', 'lecture', 'musique'] 
    } 
}
On "bind" les méthodes et variables qui nous intéressent au this de
HomeController
Il faut penser à déclarer le controller dans le HTML grâce à la
directive ngController
<body ng­app="monApplicationAngular"> 
    <div ng­controller="HomeController as home"> 
        Nom de l'utilisateur : {{ home.user.name }} 
        Loisir n° 3 de l'utilisateur : {{ home.user.loisirs[2] }} 
    </div> 
</body>
On utilise la syntaxe controllerAs, indissociable du binding à
l'instance du controller (le this côté JS), en spéci剭녲ant un alias pour
notre controller : home (arbitraire)
-Do You Like Your Angular Controllers with or without Sugar? @John_Papa
$scope
Dans le javascript, on aurait pu aussi lier le modèle à $scope au lieu
de this, sans utiliser la syntaxe controllerAs :
function HomeController($scope) { 
    $scope.user = { 
        name: "Pierric", 
        loisirs: ['ski', 'lecture', 'musique'] 
    } 
}
Côté HTML :
<div ng­controller="HomeController"> 
    Nom de l'utilisateur : {{ user.name }} 
    Loisir n° 3 de l'utilisateur : {{ user.loisirs[2] }} 
</div>
Les limites de $scope
<div ng­controller="MainCtrl">
    {{ title }} 
    <div ng­controller="AnotherCtrl"> 
        {{ title }} 
        <div ng­controller="YetAnotherCtrl"> 
            {{ title }} 
        </div> 
    </div> 
</div>
On préfèrera limiter $scope à l'utilisation de méthodes qui en
dépendent telles que $watch, $on ou $broadcast
-
function HomeController($scope) { 
    var vm = this; 
    vm.username = "Pierric"; 
    $scope.$on('someEventFiredFromElsewhere', function (event, data) { 
        // do something! 
    }); 
}
Digging into Angular’s “Controller as” syntax @toddmotto
<demo />
Les directives
ngApp, ngController, ngModel, ... sont des directives
Ce sont des marqueurs positionnés sur des éléments du DOM qui
indiquent à angular quel comportement attacher à un élément et/ou
quelle transformation y apporter
De nombreuses directives sont intégrées nativement :
https://code.angularjs.org/1.4.11/docs/api/ng/directive
Directives de template
: insère ou pas un élément dans le DOM en fonction de la
valeur de l'attribut
ngIf
<div ng­if="isVisible">I'm gonna disappear</div>
: permet de parcourir les éléments d'un tableau et
d'a皉푰cher leur valeur
ngRepeat
<div ng­repeat="user in users">{{ user.name }}</div>
: modi剭녲e le contenu d'un élément suivant la valeur d'une
expression
ngSwitch
<div ng­switch="isEditable"> 
    <div ng­switch­when="false">Name : {{ user.name }}</div> 
    <div ng­switch­when="true"><input type="text" ng­model="user.name"></div> 
</div>
Directives de style
/ : modi剭녲e la visibilité d'un élément du DOM
suivant la valeur de l'expression en paramètre
ngShow ngHide
<div ng­hide="hidden">Hello hide</div> 
<div ng­show="hidden">Hello show</div>
: conditionne dynamiquement les classes d'un élément du
DOM suivant la valeur d'expressions
ngClass
<p ng­class="{bold: important, red: error}">Map Syntax Example</p>
: modi剭녲e la valeur de l'attribut disabled suivant
l'expression spéci剭녲ée
ngDisabled
<button ng­disabled="isDisabled">Disabled</button>
Directives d'action
: permet d'appeler une fonction ou d'évaluer une
expression lors d'un clic sur l'élément
ngClick
<div ng­click="click()">Click me!</div> 
<button ng­click="count = count + 1" ng­init="count = 0">Increment</button>
/ : associe des actions à des événements
claviers
ngKeydown ngKeyup
<input type="text" ng­keydown="down()" ng­keyup="up()">
: spéci剭녲e l'action à e튵䎣ectuer pour l'envoi d'un
formulaire. Ne pas combiner avec ngClick !
ngSubmit
<form ng­submit="submit()" ng­controller="SimpleFormController"> 
    <input type="text" ng­model="text" name="text"> 
    <input type="submit" id="submit" value="Submit"> 
</form>
<demo />
Les Filtres
Les 剭녲ltres permettent de formatter et de... 剭녲ltrer (!) les expressions
auxquelles ils sont appliqués :
{{ expression | filter }} 
{{ expression | filter1 | filter2 }} <!­­ Ils peuvent être combinés ­­>
{{ expression | filter:arg1:arg2 }} <!­­ On peut passer des arguments ­­>
Exemples :
{{ 'Mon texte' | uppercase }} 
{{ '25.465' | number:2 | currency:'$'}} <!­­ seulement 2 décimales ­­>
Liste des 剭녲ltres natifs :
https://docs.angularjs.org/api/ng/剭녲lter
Soit le tableau suivant dans un controller:
var jb = {name: 'JB', gender: 'male'}, 
    cyril = {name: 'Cyril', gender: 'male', birth: '1990­11­25'}, 
    agnes = {name: 'Agnes', gender: 'female', birth: '1991­07­22'}, 
    cedric = {name: 'Cedric', gender: 'male', birth: '1992­02­22'}; 
vm.ninjas = [jb, cyril, agnes, cedric];
Avec le HTML suivant :
<p>{{ ninjas | orderBy:'name' | limitTo:2 }}</p> 
<div ng­repeat="ninja in ninjas"> 
    {{ ninja.birth | date:'yyyy' }} 
</div>
On obtiendra :
[ 
    {"name":"Agnes","gender":"female","birth":"1990­07­22"}, 
    {"name":"Cedric","gender":"male","birth":"1990­02­22"} 
] 
1990 
1991 
1992
Le filtre Filter
剭녲lter permet d'appliquer un 剭녲ltre personnalisé aux éléments d'un
tableau
<input type="text" ng­model="searchText"> 
<table id="searchTextResults"> 
    <tbody><tr><th>Name</th><th>Birth date</th></tr> 
    <tr ng­repeat="ninja in ninjas | filter:searchText"> 
        <td>{{ friend.name }}</td> 
        <td>{{ friend.birth | date:'dd/MM/yyyy' }}</td> 
    </tr> 
</tbody></table>
<label>Any: <input ng­model="search.$"></label><br> 
<label>Name only <input ng­model="search.name"></label><br> 
<label>Gender only <input ng­model="search.gender"></label><br> 
<label>Equality <input type="checkbox" ng­model="strict"></label><br> 
<table id="searchObjResults"> 
    <tbody><tr><th>Name</th><th>Gender</th></tr> 
    <tr ng­repeat="ninja in ninjas | filter:search:strict"> 
        <td>{{ ninja.name }}</td> 
        <td>{{ ninja.gender }}</td> 
    </tr> 
</tbody></table>
<demo />
Time for practice !
- Unit 1Learn AngularJS | Codecademy
- Levels 1 / 2 / 3Shaping up with AngularJS | CodeSchool
Créer ses directives
L'avenir du web est aux : découpage des
fonctionnalités en modules réutilisables indépendamment.
Web Components
Les directives sont un avant-goût et permettent d'implémenter une
partie de cette logique.
peut devenir :
<div> 
    <h1 class="title">{{ book.title }}</h1> 
    <h2 class="author">{{ book.author }}</h2> 
    <div class="extract">{{ book.extract }}</div> 
</div>
<book­details data­book="main.book"></book­details>
Fichier bookDetails.directive.js :
angular.module('myApp') 
       .directive('bookDetails', bookDetails);  // camelCase côté JS ! 
        
function bookDetails() { 
    return {            // Une directive retourne un objet de "configuration" 
        restrict: 'E',  // La directive doit être appelée sous forme d'élément 
        scope: {        // On crée un nouveau scope isolé propre à la directive 
            book: '='   // On récupère l'objet passé à l'attribut correspondant 
        }, 
        templateUrl: 'bookDetails.tpl.html',  // Indique où aller chercher le HTML 
    }; 
}
Fichier bookDetails.tpl.html :
<div> 
    <h1 class="title">{{ book.title }}</h1> 
    <h2 class="author">{{ book.author }}</h2> 
    <div class="extract">{{ book.extract }}</div> 
</div>
restrict : indique comment doit être appelée la directive dans le
HTML - A pour attribut, E pour élement et C pour classe CSS. On
peut les combiner, par exemple 'AEC'.
scope : crée un scope isolé pour la directive. On récupère les
éléments du scope englobant via les attributs. '@' pour passer une
valeur (chaîne de caractères), '=' pour du two-way binding sur un
objet.
controller : une directive peut avoir son propre controller.
controllerAs : permet de spéci剭녲er un alias pour le controller,
comme avec ng-controller = ... as ...
bindToController : indissociable de ControllerAs, lie les propriétés à
l'instance du controller plutôt qu'au scope.
... 
controller: function () { 
    var vm = this;     
    vm.selectBook = function () { ... } 
}, 
controllerAs: 'bookDetails', 
bindToController: true 
...
https://docs.angularjs.org/api/ng/service/$compile
<demo />
Time for practice !
- Unit 2Learn AngularJS | Codecademy
- Level 4Shaping up with AngularJS | CodeSchool
Les services
Les services sont des objets dans lesquels on met le code
correspondant à la logique métier de l'application. Ils sont aussi
utilisés pour organiser le code partagé de l'application.
Les services sont :
Lazy : paresseux, ils ne sont instanciés que lorsque l'application en
a besoin
Singletons : ils seront instanciés une seule fois et cette instance
est ensuite utilisée partout
Les services natifs
: permet de faire simplement des requêtes AJAX. Renvoie
une promise avec une callback de succès et une autre d'échec.
$http
$http({method: 'GET', url: '/serverUrl'}) 
    .success(function(data, status, headers, config){ ... }) 
    .error(function(data, status, headers, config){ ... });
: service plus haut niveau, utilisé pour interagir avec des
. Nécessite le module ngResource.
$resource
API REST
{ 'get':    {method:'GET'}, 
  'save':   {method:'POST'}, 
  'query':  {method:'GET', isArray:true}, 
  'remove': {method:'DELETE'}, 'delete': {method:'DELETE'} };
var Poneys = $resource('/races/:raceId/poneys/:poneyId',  
    { raceId: 24, poneyId: '@id'}, { run: { method: 'PUT' }}); 
var fury = Poneys.save({ name: 'Fury Red'});
: rend accessible l'URL de la page actuelle à notre
application et expose plusieurs méthodes.
$location
// avec l'url http://example.com/#/some/path?foo=bar&baz=xoxo 
var path = $location.path(); // => "/some/path" 
var searchObject = $location.search(); // => {foo: 'bar', baz: 'xoxo'}
/ : permettent de wrapper setTimeout et
setInterval dans le cycle de vie de l'application angular.
$timeout $interval
var delayedFn = $timeout(function(){ ... }, 1000) // Après 1 seconde. 
var recurringFn = $interval(function(){ ... }, 1000, 0) // Chaque seconde.
Autres wrappers ($window, $document...) et services natifs :
https://docs.angularjs.org/api/ng/service
Les Promises
Nouveauté de l'EcmaScript 6, implémentée via le service $q.
Utilisée lors de traitements asynchrones tels que les requêtes AJAX
avec $http.
Une promise peut avoir deux résultats : succès ou échec.
$http.get(...) 
    .then(function(data){ 
        // succès, promise résolue 
    }, function(error){ 
        // erreur, promise rejetée 
});
$q
function asyncGreet(name) { 
    var deferred = $q.defer(); // On crée un objet deferred 
    $timeout(function() { // Ici on crée artificiellement un délai 
        deferred.notify('About to greet ' + name + '.'); 
     
        if (okToGreet(name)) { 
            deferred.resolve('Hello, ' + name + '!'); // succès 
        } else { 
            deferred.reject('Greeting ' + name + ' is not allowed.'); // échec 
        } 
    }, 1000); 
     
    return deferred.promise; // On retourne la promise de deferred 
} 
var promise = asyncGreet('Robin Hood'); // La fonction retourne une promise 
promise.then(function(greeting) { 
    alert('Success: ' + greeting); // En cas de succès 
}, function(reason) { 
    alert('Failed: ' + reason); // En cas d'échec 
}, function(update) { 
    alert('Got notification: ' + update); // Indication de progression 
});
<demo />
L'injection de dépendance (DI)
Pour pouvoir utiliser un composant dans un autre, angular utilise un
système d'injection de dépendance.
function HomeController($scope, $http) { ... } 
// function HomeController($http, $scope) { ... } // équivalent !
HomeController.toString(); // "function HomeController($scope, $http) { ... }"
Pour éviter les problèmes en cas de mini剭녲cation du javascript, on
"annote" les composants :
HomeController.$inject = ['$scope', '$http']; 
function HomeController($scope, $http) { ... } // Il vaut mieux garder le même ordre...
Time for practice !
- Unit 3Learn AngularJS | Codecademy
- Level 5Shaping up with AngularJS | CodeSchool
ngRoute
ngRoute est le module angular de base chargé du routage.
Il est composé d'une directive ngView, d'un $routeProvider et de 2
services : $route et $routeParams.
ngView indique quelle partie de la SPA sera mise à jour :
<div ng­view=""></div>
$routeProvider
$routeProvider permet de déterminer les routes de l'application et
de faire le lien entre URL, template et controller.
angular 
    .module("monApplicationAngular") 
    .config(configure); 
     
function configure($routeProvider) { 
    $routeProvider 
        .when('/races/:raceId?', { // raceId est un paramètre facultatif 
            templateUrl: 'races.html', 
            controller: 'RacesController' // Remplace ng­controller="..." 
        }) 
        .when('/', { 
            templateUrl: 'poneys.html', 
            controller: 'PoneysController' 
            controllerAs: 'poneys' // Remplace ng­controller="... as ..." 
        }) 
        .otherwise('/'); // Si l'url ne correspond pas, redirection 
}
$routeParams
Service permettant de déterminer les paramètres de la route.
Combinaison de $location.search() et $location.path().
// Avec une url = http://www.example.com/#/races/13?poney=10 
$routeParams ==> { raceId: "13", poney: "10" }
Time for practice !
- Units 4 / 5Learn AngularJS | Codecademy
Ressources utiles
- ebook - [fr]
chez video2brain - [fr]
par - [fr]
par - [fr]
sur MDN - [fr]
Le guide du développeur
Devenez un ninja avec AngularJS
2 formations vidéos
Formation vidéo AngularJS @gra剭녲kart_fr
Le guide de style Angular @john_papa
Une réintroduction à Javascript

Intro à angular