$http
$http
$http({method: 'GET', url: 'http://www.google.com/'})
.success(function(data, status, headers, config) {
// Success
})
.error(function(data, status, headers, config) {
// Error
});
$http.get
$http.head
$http.post
$http.put
$http.delete
$http.get('http://www.google.com/');
$http.post('/users', {
data: {
username: 'Toto',
password: 's3cret',
}
});
$http
params
: Paramètres de la requête (?key1=value1&key2=value2
).headers
: En-têtes à ajouter à la requête.cache
: Activer le cache.timeout
: Changer le timeout de la requête.Les différentes méthodes HTTP pour le REST.
GET
: Récupérer une liste d'objets (/users
) ou un objet en particulier (/users/123
).POST
: Créer un nouvel objet (/users
).PUT
: Modifier un objet existant (/users/123
).DELETE
: Supprimer un objet existant (/users/123
).angular-resource
.$resource
var User = $resource('/users/:userid', {
userId: '@id',
});
// GET /users
User.get(function(users) {
// Success
}, function(err) {
// Error
});
// GET /users/123
User.get({
id: '123',
}, function(user) {}, function(err) {});
// GET /users
User.query(function(users) {
var user = users[0];
}, function(err) {});
$resource
est un service permettant de faciliter la gestion d'objets par requêtes REST.
$resource
est dans le module ngResource.
.get()
permet de récupérer un ou des objets. query()
permet de récupérer une liste d'objet.
// POST /users/123
User.save({}, {
username: 'Toto',
password: 's3cret',
}, function(user) {}, function(err) {});
// DELETE /users/123
User.delete({
id: '123'
}, {}, function(resp) {}, function(err) {});
User.remove({
id: '123'
}, {}, function(resp) {}, function(err) {});
// Exactement la même chose qu'au dessus
User.delete({}, {
id: '123'
}, function(resp) {}, function(err) {});
save(parametres, data)
pour sauvegarder les données.
delete
alias de remove
Les "paramètres" de delete
peuvent être mis en tant que "data".
$save
/ $delete
/ $remove
// POST /users/123
User.get({id: '123'}, function(user) {
user.password = 'n0t s0 s3cret';
user.$save;
});
// Asynchrone, référence vide pour le moment.
$scope.user = User.get({id: '123'});
User.get({id: '123}, function(user) {
$scope.user = user;
});
$save
, $delete
et $remove
feront les requêtes HTTP en fonction de l'objet.
L'appel est asynchrone est la valeur est vide tant que la requête n'est pas fini.
Restangular est un service plus avancé pour la gestion des backend REST.
// GET /users
Restangular.all('users').getList().then(function(users){
$scope.users = users;
});
// GET /users/123
Restangular.one('users', 123).get().then(function(user){
$scope.user = user;
});
// GET /users/123/friends
Restangular.one('users', 123).all('friends').getList().then(function(friends){
$scope.user = user;
});
Ajoute des dépendances (Lodash
).
Utilise les promesses.
angular-websocket
.var ws = new WebSocket("ws://localhost:8000/socket/");
ws.onopen = function(){
// WebSocket ouverte
};
ws.onmessage = function(message) {
// Nouveau message
};
ws.send('Message');
Une promesse permet de résoudre une valeur de manière asynchrone (ou non) d'une manière "synchrone".
User.get(fromId, function(user){
user.friends.find(toId, function(friend) {
user.sendMessage(friend, message, function(){
// Message envoyé
}, function(err) {
// Erreur lors de l'envoi du message
});
}, function(err) {
// Impossible de trouver l'ami
})
}, function(err) {
// Impossible de trouver l'utilisateur
});
Imaginont un service User permettant de récuperer un utilisateur.
User.get(fromId)
.then(function(user){
return user.friends.find(toId);
}, function(err) {
// Impossible de trouver l'utilisateur
})
.then(function(friend) {
return user.sendMessage(friend, message);
}, function(err) {
// Impossible de trouver l'ami
}).then(function() {
// Message envoyé
}, function(err) {
// Erreur lors de l'envoi du message
});
$http
, $timeout
, $interval
retourne des promesses !$http.get('http://www.google.com/').then(function(data) {
// data – {string|Object} – Le corps de la réponse transformé (JSON => Objet).
// status – {number} – Code HTTP de la réponse.
// headers – {function([headerName])} – Fonction permettant de récuperer les en-têtes.
// config – {Object} – La configuration utilisé lors de la requête.
// statusText – {string} – Le status HTTP en texte.
var response = data.data;
});
var deferred = $q.defer();
// Résoud la promesse
deferred.resolve(value);
// Rejette la promesse
deferred.reject(reason);
// Informe sur le status de la promesse
deferred.notify(value);
return deferred.promise;
$q.all(promises)
$q.reject(reason)
$q.when(value)
reject
et when
crééent des promesses à partir d'une valeurs.
.then(successFn, errFn, notifyFn)
.catch(errFn)
then
retourne une promesse. Les promesses peuvent donc être chainées.
catch
peut être utilisé à la place du parametre errFn.
angular.module('myApp', [])
.factory('UserService', ['$q', '$resource', function($q, $resource) {
var User = $resource('/users/:userid', {userId: '@id'});
return {
getUsers: function() {
var deferred = $q.defer();
User.query(function(users) {
deferred.resolve(users);
}, function(err) {
deferred.reject(err);
});
return deferred.promise;
},
};
}]);
.controller('UserController', function($scope) {
$scope.users = '';
UserService.getUsers().then(function(users) {
$scope.users = users;
}, function(err) {
// Erreur
});
});
Dans cet exemple on va juste récuperer une liste d'utilisateur depuis un backend REST.
angular.module('myApp', [])
.controller('ViewController', function($scope, $http, $q) {
$scope.vocabularies = {};
$scope.cities = {};
$http.get('/vocabularies/cities').then(function(cities) {
$scope.vocabularies.cities = cities;
var promises = [];
for (var i = 0; i < $scope.vocabularies.cities.length; i++) {
city = $scope.vocabularies.cities[i];
promises.push($http.get('/cities/'+ city.id));
}
return $q.all(promises);
}).then(function(cities) {
$scope.cities = values;
});
});
});
Dans cet exemple on va récuperer une liste de ville depuis un vocabulaire puis récupérer les informations de toutes les villes.
$q.all()
permet d'attendre que toutes les requêtes pour les villes aient été faites.
angular.module('myApp', [])
.controller('ViewController', function($scope, $http, $q) {
$scope.vocabularies = {};
$scope.cities = {};
// Ira dans la fonction "Erreur 1" si il y a une erreur
$http.get('/vocabularies/cities').then(function(cities) {
$scope.vocabularies.cities = cities;
// Ira dans la fonction "Erreur 1" si il y a une erreur
$http.get('/cities/1').then(function(city) {
// OK
});
// Ira dans la fonction "Erreur 2" si il y a une erreur
$http.get('/cities/2').then(function(city) {
// OK
}, function(err) {
// Erreur 2
});
}, function(err) {
// Erreur 1
});
});
});
L'erreur remonte jusqu'a la promesse qui pourra la gérer.
todo
avec :/github
.angular
avec $http
.https://api.github.com/orgs/angular/repos
/github/:project
.angular-resource
bower install --save angular-resource
angular-resource.js
dans index.html
.$resource
).https://api.github.com/repos/angular/{projet}
https://api.github.com/repos/angular/{projet}/pulls
npm
permet d'installer des paquets Node.js.
Un fichier package.json
permet de décrire un projet et contient ses dépendances ainsi que les commandes permettant de le tester/lancer.
npm init # Créer un fichier package.json
npm install # Utilise package.json
npm install bower # Installe un paquet de manière locale
npm install --save bower # Installe un paquet et l'ajoute aux dépendances
npm install --save-dev bower # Installe un paquet et l'ajoute aux dépendances de développements
npm install -g bower # Installe un paquet de manière globale
npm install bower==1.3.12 # Installe une version précise
Voir le fichier package.json
d'angular-seed
.
Bower
est une application Node.js permettant de gerer les dépendances client.
Un fichier bower.json
contient les dépendances. Un fichier .bowerrc
permet la configuration.
bower init # Créer un fichier bower.json
bower install # Installe les dépendances du projet
bower install angular # Installe un paquet
bower install --save angular # Installe un paquet et l'ajoute aux dépendances
bower install --save-dev angular # Installe un paquet et l'ajoute aux dépendances de développements
bower install git://github.com/user/package.git
bower install http://example.com/script.js
Voir le fichier bower.json
et .bowerrc
d'angular-seed
.
Grunt est une application Node.js permettant d'automatiser des taches. Il se base sur un système de plugins permettant une gestion souple des taches à effectuer.
npm install -g grunt-cli
npm install --save-dev grunt grunt-contrib-concat grunt-contrib-uglify grunt-contrib-watch
Les taches sont enregistré dans un fichier Gruntfile.js
.
module.exports = function(grunt) {
// Project configuration.
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
concat: {
build: {
src: ['app/**/*.js', 'app/bower_components/angular/angular.min.js'],
dest: 'app/app.js',
}
},
uglify: {
build: {
src: 'src/app.js',
dest: 'build/app.min.js'
}
},
watch: {
build: {
files: ['app/**/*.js'],
tasks: ['default'],
}
}
});
// [...]
Définition des taches.
// [...]
// Load the plugins.
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-contrib-watch');
// Default task(s).
grunt.registerTask('default', ['concat', 'uglify']);
};
Chargement des plugins + enregistrement des taches (dont la tache 'default').
grunt # Effectue la tache "default"
grunt concat # Effectue toute les taches du plugin "concat"
grunt concat:build # Effectue uniquement la tache "build" de "concat"
grunt watch # Effectue la tache watch : surveille les changements
Gulp
est également un automatiseur de tache et fonctionne également sur un système de plugins.
Les taches sont enregistré dans un fichier gulpfile.js
.
var gulp = require('gulp');
var concat = require('gulp-concat');
var rename = require('gulp-rename');
var uglify = require('gulp-uglify');
gulp.task('js', function () {
return gulp.src(['app/**/*.js',
'app/bower_components/angular/angular.min.js'])
.pipe(concat('app/app.js'))
.pipe(gulp.dest('./app/'))
.pipe(uglify())
.pipe(rename('app.min.js'))
.pipe(gulp.dest('./app/'));
});
gulp.task('default', ['js']);
gulp.task('watch', function () {
gulp.watch(['./app/**/*.js'], ['js']);
});
bower.json
(--save
).http://fortawesome.github.io/Font-Awesome/examples/
Grunt
puis gulp
.index.html
. Il ne doit rester que le fichier minifié.angular-generator
generator-gulp-angular
yo
> Install a generator
# ou
npm install -g angular-generator
mkdir myapp
cd myapp
yo
> Run the Angular generator
# ou
yo angular
grunt serve
grunt test
yo --help
yo angular:route myRoute
yo angular:controller myController
yo angular:directive myDirective
yo angular:filter myFilter
yo angular:view myView
yo angular:service myService
yo angular:factory myService
yo angular:value myService
yo angular:constant myService
grunt build
ls dist
console.log();
console.table();
debugger;
On va aussi pouvoir mettre des breakpoints directement dans la console de debug de différente manières.
var rootEle = document.querySelector("html");
var ele = angular.element(rootEle);
// Ou bien, avec l'inspecteur
var ele = angular.element($0);
ele.scope();
ele.controller();
ele.inheritedData();
Extension Chrome permettant d'inspecter :
console.log()
pour afficher les taches à leur création.Fichier JS :
app = angular.module('myApp', ['pascalprecht.translate']);
app.config(function($translateProvider){
$translateProvider.translations('en', {
WELCOME: 'Welcome',
});
$translateProvider.translations('fr', {
WELCOME: 'Bienvenue',
});
$translateProvider.preferredLanguage('fr');
});
app.controller('TranslateController', function($translate, $scope){
$scope.changeLanguage = function(lang) {
$translate.uses(lang);
};
});
Fichier HTML :
<h1>{{ 'WELCOME' | translate }}</h1>
<h1 translate>WELCOME</h1>
<div ng-controller="TranslateController">
<button ng-click="changeLanguage('en')">English</button>
<button ng-click="changeLanguage('fr')">Français</button>
</div>
Fournit un filtre et une directive translate
. Les traductions sont en JSON.
Peu pratique pour des applications complexes.
app.config(function($translateProvider){
$translateProvider.useUrlLoader('/locales/translations.json');
$translateProvider.preferredLanguage('fr');
// Fichier '/locales/tranlsations.json?lang=fr'
});
app.config(function($translateProvider){
$translateProvider.useStaticFilesLoader({
prefix: '/locales/',
suffix: '.json',
});
$translateProvider.preferredLanguage('fr');
// Fichier '/locales/fr.json'
});
Toujours peu pratique pour une personne non technique.
Fichier JS :
app = angular.module('myApp', ['gettext']);
app.run(function(gettextCatalog){
gettextCatalog.setCurrentLanguage('fr');
// Vérifier que toutes les traductions soit présentes.
// Les éléments non traduits auront "[MISSING]:" de préfixés.
gettextCatalog.debug = true;
});
app.controller('TranslateController', function($scope, gettextCatalog){
$scope.changeLanguage = function(lang) {
gettextCatalog.setCurrentLanguage(lang);
};
});
app.controller('ExampleController', function($scope, gettextCatalog){
$scope.persons = 2;
$scope.name = "Foo";
});
Un fichier .js
supplémentaire contenant les traduction est ajouté à l'application.
Nous verrons plus loin comment générer ce fichier JS.
Fichier HTML :
<div ng-controller="ExampleController">
<h1 translate>Welcome</h1>
<input type="text" placeholder="{{ 'Username' | translate }}" />
<div translate translate-n="personsCount"
translate-plural="{{$count}} persons">One person</div>
<div translate-comment="Hello message" translate>Hello {{ name }}</div>
</div>
<div ng-controller="TranslateController">
<button ng-click="changeLanguage('en')">English</button>
<button ng-click="changeLanguage('fr')">Français</button>
</div>
Filtre et directive disponible. Permet la traduction des pluriels. Permet la traduction avec variables.
.pot
).po
).js
)Extraction des textes à traduires. Intégration de ces textes dans le fichier de traduction. Traduction. Compilation.
grunt-angular-gettext
nggettext_extract: {
pot: {
files: {
'po/template.pot': ['src/views/*.html']
}
},
},
gulp-angular-gettext
gulp.task('pot', function () {
return gulp.src(['src/views/*.html'])
.pipe(gettext.extract('template.pot'))
.pipe(gulp.dest('po'));
});
poedit
permet de modifier les fichiers .po
.
.po
à partir du .pot
.po
à partir du .pot
.po
Puis sauvegarder.
grunt-angular-gettext
nggettext_compile: {
all: {
files: {
'src/js/translations.js': ['po/*.po']
}
},
},
gulp-angular-gettext
gulp.task('po', function () {
return gulp.src(['po/*.po'])
.pipe(gettext.compile())
.pipe(gulp.dest('src/js/'));
});
Pensez à inclure le fichier JS ainsi créer dans l'application.
angular-gettext
.Bootstrap sans jQuery et avec des directives.
<progressbar class="progress-striped" value="22" type="warning">22%</progressbar>
<timepicker ng-model="mytime" ng-change="changed()" hour-step="hstep"
minute-step="mstep" show-meridian="ismeridian"></timepicker>
<input type="text" class="form-control" size="8" ng-model="time" name="time" bs-timepicker>
Pas forcément les meme composant d'implémentés. Logique différente (directive element ou attribues).
<body>
<div ui-view></div>
<a ui-sref="state1">State 1</a>
<a ui-sref="state2">State 2</a>
</body>
<h1>State 1</h1>
<hr/>
<a ui-sref="state1.list">Show List</a>
<div ui-view></div>
<h3>List of State 1 Items</h3>
<ul>
<li ng-repeat="item in items">{{ item }}</li>
</ul>
Permet de faire des vues dans des vues ainsi que des vues multiples sur la même page. Permet également de nommer ses vues.
<h1>State 2</h1>
<hr/>
<a ui-sref="state2.list">Show List</a>
<div ui-view></div>
<h3>List of State 2 Things</h3>
<ul>
<li ng-repeat="thing in things">{{ thing }}</li>
</ul>
myApp.config(function($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise("/state1");
$stateProvider
.state('state1', {
url: "/state1",
templateUrl: "partials/state1.html"
})
.state('state1.list', {
url: "/list",
templateUrl: "partials/state1.list.html",
controller: function($scope) {
$scope.items = ["A", "List", "Of", "Items"];
}
})
.state('state2', {
url: "/state2",
templateUrl: "partials/state2.html"
})
.state('state2.list', {
url: "/list",
templateUrl: "partials/state2.list.html",
controller: function($scope) {
$scope.things = ["A", "Set", "Of", "Things"];
}
});
});
<body>
<div ui-view="viewA"></div>
<div ui-view="viewB"></div>
<a ui-sref="route1">Route 1</a>
<a ui-sref="route2">Route 2</a>
</body>
myApp.config(function($stateProvider) {
$stateProvider
.state('index', {
url: "",
views: {
"viewA": { template: "index.viewA" },
"viewB": { template: "index.viewB" }
}
})
.state('route1', {
url: "/route1",
views: {
"viewA": { template: "route1.viewA" },
"viewB": { template: "route1.viewB" }
}
})
.state('route2', {
url: "/route2",
views: {
"viewA": { template: "route2.viewA" },
"viewB": { template: "route2.viewB" }
}
});
});
Surveille les modifications de variables et les propages dans l'application.
En HTML :
<input ng-model="name" type="text" />
Ou en JS :
$scope.name = 'Toto';
var unregister = $scope.$watch('name', function(newVal, oldVal){
console.log('name changed : '+ oldVal +' => '+ newVal);
});
// Remove the $watch
unregister();
Execute une fonction plus tard.
$scope.$evalAsync(function(){
console.log('evalAsync');
});
angular.forEach([1, 2, 3, 4], function(value){
console.log(value);
});
angular.forEach({firstname: 'Foo', lastname: 'Bar'}, function(value, key){
console.log(key +' = '+ value);
});
var json = angular.toJson({firstname: 'Foo', lastname: 'Bar'});
var obj = angular.fromJson("{firstname: 'Foo', lastname: 'Bar'}");
if (angular.isArray([1, 2, 3])) {
console.log('OK !');
}
var obj = {firstname: 'Foo', lastname: 'Bar'};
var newObj = angular.copy(obj);
newObj.name = "Toto";
obj.name == "Foo"; // OK
Infos nécessaire pour Protractor
ou Batarang
. À n'utiliser qu'en production.
app.config(['$compileProvider', function ($compileProvider) {
$compileProvider.debugInfoEnabled(false);
}]);
// Réactiver avec :
angular.reloadWithDebugInfo();
One-way binding : {{ ::expression }}
Table of contents | t |
---|---|
Exposé | ESC |
Autoscale | e |
Full screen slides | f |
Presenter view | p |
Source files | s |
Slide numbers | n |
Blank screen | b |
Notes | 2 |
Help | h |