ng-repeat
Cette directive permet d'itérer sur une collection :
1. Array
2. Object
Au lieu du traditionnel for dans le code
JavaScript, nous n'aurons ici qu'un simple
attribut HTML
Chaque itération de la boucle reçoit son
propre scope, qui possède la propriété $index
http://codepen.io/Ambient-IT/pen/qdRGXr?editors=101
Exercice
Instructions :
1. Utiliser la directive ng-repeat pour afficher toutes les informations
stockées dans le tableau du controller
2. Afficher l'image en premier puis un titre suivis d'un lien
3. Ecrire une methode "RemoveFramework" dans le controlleur, qui
prend un number en parametre et supprime le framework
correspondant dans le tableau frameworks
4. Vous pouvez utiliser les classes Bootstrap pour votre liste
http://codepen.io/Ambient-IT/pen/BNdoEE?editors=101
Les Filtres
Les filtres sont des composants fournis par
Angular qui permettent de modifier la
manière dont le modèle est affiché par la vue.
http://codepen.io/Ambient-IT/pen/YXNbbj?editors=101
Combinée avec ng-repeat, ils nous permettent
d'améliorer le comportement de notre collection :
limiter le nombre d'élément affichés
filtrer a l'aide d'un input (par exemple)
http://codepen.io/Ambient-IT/pen/GgQyaj
Exercice
Instructions :
1. Reprendre la fin de l'exercice précedent.
2. Rajouter une input et appliquer un filtre sur la liste en
filtrant par name.
Création de directives simples
Composants réutilsables ou simples décorateurs
Directive Hello World
Nous allons créer une directive helloWorld qui affichera
simplement "Hello, World !" à l'endroit où elle est utilisée
Cette dernière sera ensuite utilisable comme une extension
au langage html.
<hello-world></hello-world>
Hello World - Template
function helloWorldDirective(){ <section ng-app="app">
return { <hello-world>
restrict: 'E',
template: '<div class="panel">Hello, World !</div>' </section>
}
}
angular.module('app', [])
.directive('helloWorld',helloWorldDirective);
http://codepen.io/Ambient-IT/pen/PqjvME?editors=101
Hello World - TemplateUrl
function helloWorldDirective(){ /hello/hello.tpl.html
return {
restrict: 'E', <div class="panel">
templateUrl: '/hello/hello.tpl.html' Hello, World !
} </div>
}
angular.module('app', [])
.directive('helloWorld',helloWorldDirective);
<section ng-app="app">
<hello-world>
</section>
Restrict
A la création d'une directive, on peut spécifier de quelle manière elle peut
être utilisée dans les templates HTML
On spécifie pour cela une ou plusieurs valeurs dans l'option restrict :
E (element/balise)
A (attribut)
C (classe CSS)
M (commentaire HTML)
Par défaut, la directive sera de type A (attribut)
Fonction link
La fonction link est exécutée une fois pour chaque instance de la directive,
lors de son initialisation. On l'utilise surtout dans le cas où l'on veut
manipuler le DOM de manière programmatique
Elle reçoit quatre arguments :
scope : scope de la directive
element : élément HTML correspondant à la balise où la
directive a été appliquée
attrs : attributs HTML appliqués à l'élément
ctrls : le ou les controllers dont cette directive dépend
Le nom des arguments n'a d'importance que pour suivre la
convention. C'est l'ordre des arguments qui assure leur
injection correcte.
AngularJS & jQuery
AngularJS et jQuery fonctionnent bien ensemble.
Si jQuery est présent l'objet "element" fourni par la
méthode link sera un objet jQuery.
Dans le cas contraire, angular utilise jqLite, une version
allégée de jQuery.
jqLite
Textangular.element('.foo');
// equivalent Jquery
$('.foo');
L'objet renvoyé par angular partage un certain
nombre de méthodes avec un objet jQuery
traditionnel, comme attr ou bind.
http://docs.angularjs.org/api/ng/function/angular.element
link function - Element
angular.module('app', []) <p my-shadow>
.directive('myShadow',myShadowDirective); Pellentesque habitant morbi tristique
function myShadowDirective(){ </p>
return {
restrict: 'A', element est un objet jqLite
link: function(scope,element,attrs){
element.toggleClass('shadowed');
}
}
}
On peut donc manipuler notre element
html comme on le ferait avec jQuery
http://codepen.io/Ambient-IT/pen/jPwjEX
Binder des évènements
angular.module('app', [])
.directive('myShadow',myShadowDirective);
function myShadowDirective(){ Notre element est desormais clickable
return {
restrict: 'A',
link: function(scope,element,attrs){
element.toggleClass('shadowed');
element.bind('click',function(){
element.toggleClass('shadowed');
})
}
}
}
http://codepen.io/Ambient-IT/pen/aOwgZN
Services
Description
Une seule instance d’un service par application AngularJS
Equivalent à un Singleton
Le système d'injection de dépendance gère l'instanciation
On peut créer un service pour partager des données entre plusieurs
controllers
Services fournis par AngularJS
Les services fournis par le framework sont préfixés
avec « $ » :
$scope
$rootScope
$window
$timeout
$log
$q
$http
Nous allons pouvoir injecter ces différents services dans nos
controllers, nos directives ou même nos propres services
https://docs.angularjs.org/api/ng/service
Traitement asynchrone
Pyramid of doom
function doAsyncCall(data,callback){
data++;
callback(data);
}
var data = 1;
doAsyncCall(data,function(firstData){
doAsyncCall(firstdata,function(secondData){
doAsyncCall(secondData,function(thirdData){
doAsyncCall(thirdData,function(fourthData){
doAsyncCall(fourthData,function(fifthData){
DOOM doAsyncCall(fifthData,function(finalData){
//do something with finalData
});
});
});
})DDDDDD; OOOOOO});OOOOOO}MMMMMM);
$q
function MyController($q, $timeout) {
function randomPromise() {
return $q(function(resolve, reject) {
if (Math.random() < 0.5) { // true une fois sur deux
resolve('successful');
} else {
reject(new Error('not successful :('));
}
});
}
this.asyncOperation = function() {
randomPromise()
.then(function(data) {
console.log(data)
})
.catch(function(err) {
console.error(err);
});
};
};
angular.module('app', [])
.controller('MyController', MyController);
http://codepen.io/Ambient-IT/pen/waJWdv?editors=101
Chainer des promises
function doAsyncCall(data) {
return $q(function(resolve,reject) {
if(typeof data !== 'number'){
reject(new Error('error !!!'));
} else {
resolve(data++);
}
});
}
var data = 1;
doAsyncCall(data)
.then(doAsyncCall)
.then(doAsyncCall)
.then(function(newData) {
return doAsyncCall(newData);
})
.then(function(finalData) {
console.log(finalData) //affiche 4
})
.catch(function(err) {
console.error(err);
});
Traitements parallèles
function doAsyncCall(data) {
return $q(function(resolve,reject) {
if(typeof data !== 'number') {
reject(new Error('error !!!'));
} else {
resolve(data++);
}
});
}
var data = 1;
var anotherData = 2;
$q.all([
doAsyncCall(data),
doAsyncCall(anotherData),
anotherPromise
]).then(function(data) {
//data est un tableaux avec 3 entrées
}).catch(function(err){
});
$http
Le service $http va nous permettre d'effectuer
des appels AJAX vers un serveur de manière
extrêmement simple.
Toutes les méthodes de ce service retournent
des promises, augmentées des méthodes success
et error.
$http({
method : 'GET',
url : '/users',
headers : {
Authorization: 'Bearer khksjhfkjshfjkhshfkjshfuhuhgi'
}
}).success(function(data){
//do something with response's data
}).error(function(err){
//something wrong happens
})
GET
Permet d'envoyer une requête GET vers une url.
$http.get('/login',{
params : {
user : 'foo'
}
}).success(function(data){
//do something with the server's response
}).error(function(err){
//something wrong happens
})
//send an http request to /login?user=foo
POST & PUT
Permet d'envoyer une requête POST ou PUT
vers une url.
$http.post('/users',{
pseudo : 'foo',
password : 'bar'
}).success(function(data){
//do something with server response
}).error(function(err){
//something wrong happens
})
Le deuxième paramètre est l'objet envoyé dans le
corps de la requête.
Les autres methodes
Delete
$http.delete('/users/01').success(function(data){
//do something with data
}).error(function(err){
//something wrong happens
})
Head
$http.head('/users/01').success(function(data){
//do something with data
}).error(function(err){
//something wrong happens
})
Providers
Pour chaque service disponible, AngularJS fournit l'accès à
son provider
Le nom du provider est composé du nom du service, suivi par
'Provider' ($http -> $httpProvider)
Les providers ne sont injectables qu'en phase de
configuration
Cycle de vie d'un module
Config
Phase permettant de configurer les services en paramétrant leurs
providers. Seuls les constantes et providers sont injectables.
angular.module('myModule', [])
.config(function(someServiceProvider) { ... });
Run
Phase d'initialisation de l'application donnant accès aux instances des
services. Les providers ne sont plus injectables.
angular.module('myModule', [])
.run(function(someService) { ... });
Intercepteur http
angular.module('app',[])
.config(function ($httpProvider) {
$httpProvider.interceptors.push(function ($window, $log) {
return {
request: function addTokenToHeader(httpConfig) {
var token = $window.localStorage.getItem('token');
if (token) {
httpConfig.headers.Authorization = 'Bearer ' + token;
}
return httpConfig;
},
requestError: function (rejection) {
$log.error(rejection); // error object
// Return the promise rejection.
return $q.reject(rejection);
},
response: function (response) {
$log.info(response); // response object
// Return the response or promise.
return response || $q.when(response);
},
responseError: function (rejection) {
$log.error(rejection); // error object
return $q.reject(rejection);
}
};
});
});
Création de services
Pour créer nos services nous disposons de 5 méthodes :
constant
value
service
factory
provider
La méthode service
La méthode service permet d'utiliser un constructeur
JavaScript standard, on va donc utiliser le mot clef this pour définir les
propriétés du service.
module.service - Exemple
function MyService() {
this.name = 'My Service Name';
this.purpose = 'For demo only';
this.sayHello = function(name) {
return 'Hello, ' + name;
};
}
angular.module('app', [])
.service('MyService', MyService);
AngularJS instancie le service avec le mot clef new
http://codepen.io/Ambient-IT/pen/vOxXwg?editors=101
La méthode factory
Une factory n'est rien d'autre qu'une fonction qui retourne un
objet.
C'est l'objet retourné par la factory qui sera injecté dans les
autres services et controllers.
Factory - Exemple simple
function MyServiceFactory() {
return {
name: 'My Service Name',
purpose: 'For demo only',
sayHello: function(name) {
return 'Hello, ' + name;
}
}
}
angular.module('app', [])
.factory('MyService', MyServiceFactory);
Angular instancie le service en appelant la méthode factory
http://codepen.io/Ambient-IT/pen/rVyMob?editors=101
Exercice
Instructions :
1. Encapsuler le code asynchrone dans une factory.
2. Utiliser les méthodes de cette factory dans le controlleur.
http://codepen.io/Ambient-IT/pen/BNdjjX?editors=101
Factory - Exemple avancé
function PersonFactory() { Cette Factory retourne une
function Person(firstName, lastName) { fonction constructeur,
this.firstName = firstName; l'équivalent JavaScript d'une
this.lastName = lastName; classe.
}
Person.prototype.getFullName = function() { C'est légal car en JavaScript
return this.firstName + ' ' + this.lastName; une fonction est un objet.
}
Person.findById = function(id) {
// Send http request...
return new Person('John', 'Snow');
}
return Person;
}
angular.module('app', [])
.factory('Person', PersonFactory);
http://codepen.io/Ambient-IT/pen/gpmVKL?editors=101
Les méthodes constant & value
module.constant
Permet de définir des constantes. L'intérêt de cette méthode est qu'elle
permet de définir des valeurs qui seront injectables dans la phase de
configuration des autres services.
module.value
Peu utilisée, car les services déclarés ainsi ne peuvent pas dépendre
d'autres services.
Les Providers
Les providers sont des services que nous allons pouvoir
paramétrer avant que l'application n'ait complètement
demarrée (durant la phase de config).
La méthode config de notre module angular nous permet de
paramétrer nos provider,
angular.module('myApp',[])
.config(function(myServiceProvider){
//do some init job with myServiceProvider
})
Anatomie d'un provider
angular.module('myModule',[])
.provider('myService',function(){
var monParam;
this.initMethod = function(value){
monParam = value;
}
this.$get = function(){
return {
methodOne : function(){ console.log(monParam) },
methodTwo : function(){}
}
}
})
MonParam fait ici office d'attribut privé, en général un objet
de configuration.
initMethod est la méthode qui sera appelable dans le bloc
config.
$get est tout simplement le constructeur.
Provider - Exemple
(function(){ Configurable et injectable en
'use strict'; phase de configuration
function helloWorld() { name est une variable
var self = this; privée.
var name = 'Default'; $get est le constructeur
setName est une methode
self.$get = function() { utilisable en phase de
var name = this.name; configuration
return {
sayHello: function() {
return "Hello, " + name + "!"
}
}
};
self.setName = function(name) {
this.name = name;
};
}
function MyController(helloWorld) {
var self = this;
self.hellos = helloWorld.sayHello();
}
angular.module('app', [])
.provider('helloWorld', helloWorld)
.controller('MyController',MyController)
//hey, we can configure a provider!
.config(function(helloWorldProvider){
helloWorldProvider.setName('World');
})
})()
http://codepen.io/Ambient-IT/pen/oXZYvL?editors=101
Environnement de
Développement
NodeJS NPM
Environnement de développement.
Npm est le gestionnaire de paquet pour
NodeJS, permet notament d'installer gulp
et bower.
$ npm search nom-du-module
$ npm install nom-du-module
$ sudo npm install nom-du-module -g
$ npm install
$ npm update
Bower
Dans un terminal
$ sudo npm install -g bower
Outil de gestion de dépendance
front-end, sorte de npm ou de
maven orienté js front-end.
$ bower search nom-du-module
$ bower install nom-du-module
$ bower install
$ bower update
Gulp
Dans un terminal
$ sudo npm install gulp -g
Outil d'automatisation de taches.
Lance les tests
lint le code (qualimétrie)
minification du code (build)
génération de documentation
compilation Scss, Less, TypeScript ...
live-server
$ sudo npm install -g live-server
serveur de développement node.js
recharge automatiquement le navigateur
Démarer le serveur
$ cd app
$ live-server
json-server
$ sudo npm install -g json-server
permet de simuler une api REST
fonctionne grâce à un fichier .json (ici data.json)
Pour démarer le serveur
$ json-server data.json
Récuperation du code source
Dans WebStorm cliquer sur :
VCS
Checkout from version control
GIT
https://github.com/AmbientIT/AngularJs-exercice
Préparation
Installation des dépendances Démarer le serveur
$ npm i $ cd app
$ live-server
Ainsi que le web-service
$ json-server data.json
Préparation (gulp)
Les taches gulp sont à définir dans le fichier gulpfile.js
Afin de voir la liste des taches gulp disponible se
positionner dans le repertoire du projet et utiliser :
$ gulp help