AngularJS
Charles Jacquin
Préparation
Ouvrez un navigateur et rendez vous sur l'url suivante :
http://slides.com/adapteach/angularjs-1-4-stagiaire/
Table des matières
1. AngularJS in a nutshell
2. Les composants
3. Angular core
4. Environnement de développement
5. Principales directives
6. NgMaterial
7. UiRouter
8. Validations de formulaires
9. Les services
10. Gestion du modèle
11. Modules complémentaires
12. Tests unitaires et fonctionnels
AngularJS in a Nutshell
"AngularJS is a new, powerful, client-side technology that provides a way of
accomplishing really powerful things in a way that embraces and extends
HTML, CSS and JavaScript, while shoring up some of its glaring deficiencies. It
is what HTML would have been, had it been built for dynamic content."
Miško Hevery
Adoption croissante
Popularité explosive
Recrutements en hausse
Pourquoi un tel engouement ?
Facile à prendre en main
Productif
Concis
Développement structuré
Facile à tester
FUN !!!
Pourtant, pas toujours facile...
Premier projet AngularJS
On faisait comment avant ?
Dans les années 90, le web c'est…
du HTML statique
du HTML généré côté serveur (PHP, Servlets Java…)
du CSS (parfois)
Un peu de JavaScript
Dans les années 2000, on voit apparaître…
Les web services (SOAP, REST)
Les frameworks JavaScript (jQuery)
AJAX
Les frameworks MVC Client
Web 2.0
"Le web 2.0 est un méli-mélo d’outils et de sites qui encouragent la
collaboration et la participation : Flickr, YouTube, MySpace, Wikipedia et
l’ensemble de la blogosphère en sont quelques exemples. Ces sites ne sont
pas des lieux d’achat, mais des zones de partage de données électroniques
et de contact entre internautes."
Tim O’Reilley
RIA
Rich
Interactif
Dynamique
Internet
S’exécute dans un navigateur web
Avec ou sans plugin
Application
… et pas Site
Le Web "Riche"
Dans les années 90, les RIA c’est… des applets Java !
Dans les années 2000, on voit apparaître…
Adobe Flash
GWT (2006)
Silverlight (2007)
ExtJS (2007)
JavaFX (2008)
Les frameworks MVC Client
Backbone.js (2010)
Ember.js (2011)
AngularJS (2012)
Et demain ?
Orienté Composant
Orienté Modèle
jQuery est orienté DOM
L'essentiel des applications développées en jQuery reposent sur la
manipulation intensive du DOM sur un mode impératif. Pour modifier la
donnée, on modifie le DOM. Pour obtenir la donnée, on parcourt le DOM.
AngularJS est orienté Modèle
Dans une application AngularJS, la majorité du code manipule le modèle,
simple représentation objet de la donnée. La vue est ensuite définie en
fonction de l'état du modèle, sur un mode déclaratif.
Data-binding
Data Binding made right !
Data Binding en action !
<div ng-app> ng-app et ng-model sont
<h2>Hello, {{user.firstName}} {{user.lastName}}</h2> des directives.
<div class="panel">
<label>First Name</label> {{ }} permet de binder notre
<input type="text" ng-model="user.firstName"> modèle à notre vue.
<label>Last Name</label>
<input type="text" ng-model="user.lastName">
</div>
<div class="panel">
<label>First Name (again)</label>
<input type="text" ng-model="user.firstName">
<label>Last Name (again)</label>
<input type="text" ng-model="user.lastName">
</div>
</div>
http://codepen.io/Ambient-IT/pen/doNrer?editors=100
Équivalent jQuery
<div>
<input type="text">
Hello, <span id="name"></span>
</div>
$(document).ready(function() {
var $input = $('input');
var $span = $('#name');
$input.keyup(function (event) {
$span.text(event.target.value);
});
});
L'objet Angular
angular.copy
angular.isDefined
angular.equals
angular.extend
angular.merge
angular.forEach
angular.fromJson
angular.toJson
angular.is...
angular.lowercase
angular.uppercase
angular.version
https://docs.angularjs.org/api/ng#function
Fusionner deux objets
var src = { angular.extend permet de
foo: 'foo', fusionner plusieurs objet.
//ne sera pas copié
nested: { var src = {
thing: 4 foo: 'foo',
} //sera copié
nested: {
}; thing: 4
var dst = { }
bar: 'bar' };
}; var dst = {
angular.extend(dest,src); bar: 'bar'
};
var newObject = angular.extend({},src,dist);
angular.merge(dest,src);
angular.merge fusionne plusieurs
objets récursivement. (deep merge) var newObject = angular.merge({},src,dist);
Les Composants
Modules
Templates (vue)
Controllers
Scopes
Directives (extensions de HTML)
Filters
Services
Les Modules
Une application angular est un module.
Les modules angular permettent de découper l'application.
Relations de dépendances entres les modules.
Limiter au maximum le couplage en réduisant les
dépendances entre modules.
Créer un module
angular.module('nomDuModule', ['dépendance1', 'dépendance2'])
Le deuxième argument de la fonction est un tableau
contenant les noms de tous les modules dont dépend
directement celui que l'on crée.
Attention !
angular.module('nomDuModule')
Ce code ne crée pas un nouveau module, mais récupère
l'instance d'un module existant. Il est conseillé de ne pas
utiliser cette version pour éviter les confusions.
Bonnes pratiques
Un module par fichier !
On a donc un appel à la fonction angular.module() par fichier
Cela favorise un meilleur découplage de l'application
[Update] ou pas...
Dans certains environnements de développement, un module
par dossier, voire par application, peut être une solution
adaptée
Dépendances
Au lancement de l'application, toutes les dépendances
transitives sont chargées dans un injecteur unique, qui aura la
responsabilité de fournir l'injection de dépendance à toute
l'application
Attention !
Si deux modules ou deux services ont le même nom dans la
même application, l'un des deux sera écrasé de manière
transparente, la source du problème étant difficile à trouver
-> penser à une stratégie de namespacing pertinente !
Templates (vue)
Fragments de HTML réutilisables
Compilés par AngularJS
Les vues générées sont dynamiques (Data Binding)
Certaines conventions imposent l'extension .tpl.html
Template (suite)
<section>
some content
</section>
<script type="text/ng-template" id="myDialog.tpl.html">
</script>
On peut également déclarer un template
imbriqué dans un autre template .
Controllers
<section ng-app="app"> ng-controller est
<h1 ng-controller="HelloWorldController"> une directive.
{{ message }}
</h1>
<div ng-controller="AnotherController as ctrl">
{{ ctrl.content }}
</div>
</section>
$scope est un "service" function HelloWorldController($scope) {
$scope.message = "Hello, World !";
Il est injecté dans le
controlleur par le };
framework function AnotherController() {
this.content = 'Another Content';
};
angular.module('app', [])
.controller('HelloWorldController', HelloWorldController)
.controller('AnotherController', AnotherController);
http://codepen.io/Ambient-IT/pen/oXBVOR?editors=101
Scopes
Héritage de Scopes
Héritage de Scopes
Chaque controller possède un scope
Les scopes AngularJS sont organisés en
arborescence hiérarchique
Cette structure reflète l'organisation du DOM
A la racine, on trouve le $rootScope
Chaque scope hérite des propriétés de son parent
selon les règles de l'héritage par prototype
tout les scopes héritent du $rootScope (par
transitivité)
Exemple d'héritage
Avec $scope
http://codepen.io/Ambient-IT/pen/GJrLBm
Avec "controller as" (sans $scope)
http://codepen.io/Ambient-IT/pen/vOgMVg
Propagation d'événement
Exercice
Instructions :
1. Créez un module "app" et utilisez-le dans la vue
2. Créez un controlleur "MyController" au sein de votre
module et utilisez-le dans la vue avec la syntaxe
"controller as"
3. Affichez le texte "Hello World" dans votre vue par le biais
de votre controller
http://codepen.io/Ambient-IT/pen/QbMyLw?editors=101
Directives
Composants graphiques
Création ou décoration
Utilisées comme des extensions à HTML
Encapsule les manipulations du DOM
Création difficile à maîtriser
Principales Directives AngularJS
ng-app
ng-controller
ng-model
ng-bind
ng-click
ng-if
ng-show
ng-hide
ng-class
ng-href
ng-src
ng-repeat
ng-controller
Permet de lier un controlleur à un element du DOM
<section>
<section ng-controller="MyFirstCtrl">
...
</section>
<section ng-controller="MySecondCtrl as secondCtrl">
...
</section>
</section>
Amené à disparaître avec Angular 2
ng-model & ng-bind
ng-model permet de "data binder" un champ de
formulaire :
input
select
autres directives comme tinymce ou ace
...
<input type="text" ng-model="user.name"/>
<p>{{ user.name }}</p>
<p ng-bind="user.name"></p>
ng-bind permet d'afficher le contenu de notre
model, c'est l’équivalent des moustaches {{ }}.
ng-click
function MyController() {
this.logIn = function() {
alert("Login Successful");
}
}
angular.module('app', [])
.controller('MyController', MyController);
<section ng-app="app">
<div ng-controller="MyController as ctrl">
<button ng-click="ctrl.logIn()">login</button>
</div>
</section>
http://codepen.io/Ambient-IT/pen/qdRGOa?editors=101
De la même manière :
On retrouve les principaux événements natif :
ng-mouseover
ng-dblclick
ng-keypress
...
Toutes ces directives fonctionnent sur le modèle de ng-click.
ng-If
<div ng-app="app" ng-controller="LoginController as user">
<div ng-if="!user.isLogged">
<p>Please Login</p>
<button ng-click="user.isLogged = true">Login</button>
</div>
<div ng-if="user.isLogged">
<p>Welcome !</p>
<button ng-click="user.isLogged = false">Logout</button>
</div>
</div>
function LoginController() {
this.isLogged = false;
}
angular.module('app', [])
.controller('LoginController', LoginController);
http://codepen.io/Ambient-IT/pen/KpaLzY?editors=101
ng-show & ng-hide
ng-if, ng-show et ng-hide offrent un comportement similaire.
Contrairement à ng-if, ng-show et ng-hide se contentent de
masquer ou rendre visible l'element avec l'attribut CSS :
display: none; display: block;
Exercice
Instructions :
1. Faire en sorte que le paragraphe apparaisse lorsque le
pointeur de la souris survole le titre.
http://codepen.io/Ambient-IT/pen/rVzxay?editors=101
ng-class
<section ng-app="app">
<div ng-controller="MyController as vm">
<button ng-click="vm.myValue = !vm.myValue">Toggle class</button>
<p ng-class="{ 'my-class' : vm.myValue }">lorem ipsum blablabla ....</p>
</div>
</section>
function MyController() { .my-class {
this.myValue = false; color: white;
text-shadow: 2px 2px 4px black;
}
}
angular.module('app', [])
.controller('MyController', MyController);
http://codepen.io/Ambient-IT/pen/wagboY
Exercice
Instructions :
1. Appliquer ou enlever (toggle) la classe CSS "shadow" au
paragraphe lorsque l'utilisateur double-clique sur le titre.
http://codepen.io/Ambient-IT/pen/jPLWPb?editors=101
ng-href & ng-src
<section ng-app="app">
<div ng-controller="MyController as ctrl">
<img ng-src="{{ ctrl.user.picture }}" alt="{{ ctrl.user.name }}"/>
<a ng-href="{{ ctrl.user.url }}">{{ ctrl.user.name }}</a>
</div>
<section>
Pour éviter d'éventuelles erreurs function MyController(){
404, nous pouvons utiliser ces this.user = {
deux directives qui attendront name: 'foo',
que l'URL soit bien évaluée avant picture: 'http://cloud/mypicture.png',
d'afficher ou d'activer l'élément url: 'http://blog.com'
du DOM. }
};
angular.module('app', [])
.controller('MyController', 'MyController');