Académique Documents
Professionnel Documents
Culture Documents
Support de cours
1 ANGULAR JS .............................................................................................................................................................. 4
3 TYPESCRIPT ............................................................................................................................................................ 17
JULIEN HEROGUELLE 1
ANGULAR 4 Support V2.0
5 ARCHITECTURE ...................................................................................................................................................... 32
8 DIRECTIVES ............................................................................................................................................................. 60
9 PIPES ........................................................................................................................................................................ 66
8 PARTAGEONS LES DONNEES ENTRE NOS COMPOSANTS AVEC LES SERVICES .......................................... 66
9 LE ROUTAGE ........................................................................................................................................................... 66
JULIEN HEROGUELLE 2
ANGULAR 4 Support V2.0
10 HTTP ....................................................................................................................................................................... 66
11 RXJS ....................................................................................................................................................................... 66
JULIEN HEROGUELLE 3
ANGULAR 4 Support V2.0
1 ANGULAR JS
HISTORIQUE DU FRAMEWORK
Angular est un framework qui va nous permettre de créer des applications complètes en single page (type client
mail, gmail, youtube leanback) et cross-plateforme (web, mobile, desktop)
Un application Single page n’a pas besoin de recharger la page du site à chaque changement d’url. Cela permet
d’avoir des applications fluides tout en gardant une navigation simple.
DIFFERENCE FRAMEWORK/LIBRAIRIE
Une librairie est un fichier permettant d’inclure des objets, des interfaces, des fonctions préprogrammés (ex :
java.util, stdlib, math).
Alors qu’un Framework est un ensemble de plusieurs librairies, offrant un environnement de travail et ayant
comme socle commun des principes et des lignes directrices.
POURQUOI UN FRAMEWORK ?
Une application en Single page est particulièrement compliquée à développer et est d’autant plus compliquée à
lire et à maintenir. Un Framework aura préparé tout le terrain afin de rendre le développement plus simple et plus
rapide. Par principe, Angular veut rendre les développements impossibles : possibles, et les développements
possibles : évidents.
Un Framework n’étant qu’un regroupement de librairies et de fonctionnalités, il peut être développé afin de nous
laisser le choix de programmer en utilisant plusieurs langages. Angular nous offre ici la possibilité de développer
notre application en Javascript, en Dart, ou en TypeScript.
ANGULAR 2 ?
Pour sa version 2 Angular, change radicalement de point de vue de conception, et ajoute encore beaucoup de
fonctionnalités. Il est beaucoup plus performant, plus simple pour nous (et toujours conforme à l’ES6/ES2015) et
permet de faire du server-side rendering afin de pouvoir prendre en charge certaines fonctionnalités plus
facilement, comme le référencement par les moteurs de recherche par exemple.
JULIEN HEROGUELLE 4
ANGULAR 4 Support V2.0
JULIEN HEROGUELLE 5
ANGULAR 4 Support V2.0
1.2 FONCTIONNEMENT
La synchronisation automatique des données entre le modèle et la vue est permise par un mécanisme appelé
dirty-checking. AngularJS exécute en permanence une boucle qui consiste à surveiller et à détecter des
modifications sur un objet JavaScript.
POUR APPROFONDIR
• https://stackoverflow.com/questions/35469024/how-does-angular-2-change-detection-work
• https://angular.io/docs/ts/latest/api/core/index/ChangeDetectorRef-class.html
• https://angular.io/docs/ts/latest/api/core/NgZone-class.html
• What is the Angular2 equivalent to an AngularJS $watch?
AngularJS embarque un également sous-ensemble de la bibliothèque open source jQuery appelé jQLite, mais
peut aussi utiliser jQuery si elle est chargée
1.3 PHILOSOPHIE
Si nous consultons Wikipedia, nous apprenons que la conception de AngularJS est guidée par plusieurs objectifs
:
• Découpler les manipulations du DOM de la logique métier. Cela améliore la testabilité du code;
• Considérer le test d'une application aussi important que l'écriture de l'application elle-même. La
difficulté de la phase de test est considérablement impactée par la façon dont le code est structuré;
• Découpler les côtés client et serveur d'une application. Cela permet au développement logiciel des
côtés client et serveur de progresser en parallèle, et permet la réutilisabilité de chacun des côtés;
• Guider les développeurs pendant toute la durée de la construction d'une application : de la
conception de l'interface utilisateur, en passant par l'écriture de la logique métier, jusqu'au test de
l'application;
• Rendre les tâches faciles évidentes et les tâches difficiles possibles.
JULIEN HEROGUELLE 6
ANGULAR 4 Support V2.0
Pour faire cela, Google a mis en place une documentation très détaillée des lignes de conduites à suivre lors de
nos développements. Elle est accessible à cette adresse.
Elle est longue mais cependant quelques points méritent d’être soulevés.
• La documentation nous parle très vite du single responsibility principle (SRP), qui est le principe
d’encapsulation de classes. La documentation nous rappelle donc que chaque fonctionnalité de
l’application doit être encapsulée par une classe donnée afin de les compartimenter et de contrôler
au mieux chaque partie de notre application;
• La règle de l’UN. Définir UNE SEULE chose, comme UN composant, UNE classe ou UN service par
fichier. Cela rend le code plus facile à lire, plus facilement maintenable et testable. Un composant par
fichier empêche des bugs cachés, et évite de partager des variables, des closures, ou des problèmes
d’import de dépendance;
• Limiter les fichiers à 400 lignes de code maximum;
• Écrire de courtes fonctions. Cela augmente la réutilisabilité du code, elles sont plus faciles à lire et donc
à maintenir, elles évitent les bugs cachés.
Le reste de la documentation précise la plupart des conventions de nommage des fichiers et des variables.
• Les noms des fichiers sont séparés par des «-» ou des «.» comme .module.ts;
• Les noms des fichiers doivent être explicites et standardisés. Comme fonction.type.ts.
Exemple : hero-list.module.ts.
Ceci n’est qu’une liste de conventions de typage et de nommage en tous genres. Mais nous verrons que le
fonctionnement même d’Angular, suit les lignes de conduite listées plus haut, en fonctionnant à base de
compartiments réutilisables et individuellement simple.
Il n'y a pas eu d'Angular 3. Google a préféré passer directement à la version 4.0 pour diverses raisons. Cela
s'explique notamment par la volonté d’aligner tous les paquets Angular sur le même numéro de version.
JULIEN HEROGUELLE 7
ANGULAR 4 Support V2.0
Durant le cadre de cette formation sur le framework Angular, nous allons avoir besoin de plusieurs outils afin de
servir notre application et de pouvoir développer avec nos collaborateurs en toute tranquillité tout ça avec des
bonnes pratiques.
Pour cela nous avons besoin tout d’abord besoin d’un serveur web.
Par défaut l’équipe de Google nous propose de travailler avec Node.js qui est un serveur web codé en Javascript
et permettant de rendre des pages Javascript en HTML, pour lequel Angular est optimisé.
Par-dessus ça nous avons évidemment besoin d’Angular, l’équipe de Google nous propose un outil en ligne de
commande appelé Angular CLI qui va nous mâcher pas mal de travail. Il va nous permettre de rapidement mettre
en place une application avec tous les fichiers nécessaires agencés et les bonnes pratiques. Avec Git, un serveur
Node.js prêt à l’emploi, et un premier Component.
Vu que le développement des applications se déroule très souvent en collaboration avec d’autres développeurs,
Google met en place directement Git grâce à Angular CLI, nous allons donc l’installer pour pouvoir en reparler
beaucoup plus tard dans la formation.
Nous n’aborderons le fonctionnement de cet utilitaire seulement dans le chapitre annexe «Collaborer avec git»
néanmoins nous pouvons retenir certains points de cet utilitaire pour le moment.
Node.js
Git
Angular CLI
JULIEN HEROGUELLE 8
ANGULAR 4 Support V2.0
2.2 NODE.JS
Javascript a longtemps été considéré comme «un truc cool pour faire des effets sur sa page web»
Javascript est avant tout un langage de programmation au même titre que le RUBY, le C, le PHP etc.
Et un langage à part qui s'utilise vraiment différemment de Java, du C et d'un tas d'autres langages.
Oui, JavaScript peut être compliqué à utiliser, mais recèle derrière ça une vraie puissance.
Dans les années 2000, jQuery ou Moontool sont apparus et jusqu’à aujourd’hui, on a pris l'habitude de manipuler
le DOM (Document Object Model) pour affecter ses balises HTML en JavaScript et leur faire subir toutes sortes
de traitements.
Puis en 2010 Google a commencé à rendre le langage beaucoup plus rapide avec l'apparition du navigateur
Google Chrome avec le moteur d’exécution V8, puis les bibliothèques dont le nom finit par .js se sont multipliées
: Backbone.js, Ember.js, Meteor.js.
Node.js nous permet d'utiliser le langage JavaScript sur le serveur... -> JavaScript en dehors du navigateur !
Node.js bénéficie de la puissance de JavaScript = toute nouvelle façon de développer des sites web dynamiques.
On peut toujours utiliser du JavaScript côté client pour manipuler la page HTML. Cela ne change pas.
Par contre, Node.js offre un environnement côté serveur qui nous permet aussi d'utiliser le langage JavaScript
pour générer des pages web. En gros, il vient de remplacer des langages serveur comme PHP, Java EE,
etc.
Oui, et parce que JavaScript est un langage basé sur les évènements, donc Node.js est lui-même basé sur les
évènements. Du coup, c'est toute la façon d'écrire des applications web qui change ! Et c'est de là que Node.js
tire toute sa puissance et sa rapidité.
JULIEN HEROGUELLE 9
ANGULAR 4 Support V2.0
JULIEN HEROGUELLE 10
ANGULAR 4 Support V2.0
Il s'agit d'un gestionnaire de paquets. Grâce à cela, lorsque nous aurons besoin d'installer un module Node.js,
une seule commande nous permettra d'installer le module ainsi que TOUTES ses dépendances.
DEFINITION
Différences : NPM a 1 environnement global et des environnement locaux pour nos projets respectifs
Un environnement global avec une liste de package qui se trouve dans le dossier :
Pour Windows
C:\Users\nomutilisateur\npm-packages\lib\node_modules\npm\package.json
Pour OSX
/Users/julienheroguelle/.npm-packages/lib/package.json
Pour Linux
/usr/local/lib/package.json
JULIEN HEROGUELLE 11
ANGULAR 4 Support V2.0
Schéma
COMMANDES DE BASES
À chacune de ces commandes nous pouvons rajouter le nom d’un package et/ou le paramètre -g qui travaille
directement sur la table des packages globale
Nous allons justement utiliser ce paramètre pour installer l’utilitaire en ligne de commande d’Angular.
Tout d’abord vérifions que notre liste de package global est bien vide, par défaut seulement le package NPM lui-
même est requis.
Quelques explications :
• NPM est l’utilitaire que nous avons installé avec Node.js, il est commun d’exécuter une commande par
le nom de l’utilitaire associé
• list est l’instruction NPM qui permet de «lister les packages»
• Le fameux paramètre -g qui indique à NPM que nous travaillons sur la liste des packages globale
• Et pour finir le paramètre –depth=0 de l’instruction list qui indique que nous voulons le niveau 0 des
packages, c’est-à-dire seulement les packages principaux
JULIEN HEROGUELLE 12
ANGULAR 4 Support V2.0
Si nous voulons voir les dépendances que demande NPM nous n’avons qu’à remonter dans les niveaux de
profondeur avec le paramètre –depth
Résultat :
Nous voyons que NPM à besoin des packages abbrev, ansi-regex, archy etc… pour fonctionner
JULIEN HEROGUELLE 13
ANGULAR 4 Support V2.0
Tapons maintenant :
NPM va alors installer Angular cli et toutes ses dépendances tout en le rendant directement accessible dans
notre invite de commande
+ @angular/cli@6.0.8
added 248 packages from 191 contributors in 61.829s
/usr/src/app #
Nous avons dès lors accès à l’utilitaire Angular qui s’appelle en exécutant la command NG :
/usr/src/app # ng -v
_ _ ____ _ ___
/ \ _ __ __ _ _ _| | __ _ _ __ / ___| | |_ _|
/ △ \ | '_ \ / _` | | | | |/ _` | '__| | | | | | |
/ ___ \| | | | (_| | |_| | | (_| | | | |___| |___ | |
/_/ \_\_| |_|\__, |\__,_|_|\__,_|_| \____|_____|___|
|___/
/usr/src/app #
├─┬ @angular/cli@6.0.8
JULIEN HEROGUELLE 14
ANGULAR 4 Support V2.0
│ ├─┬ @angular-devkit/architect@0.6.8
Si maintenant nous relançons la commande npm list -g –depth=0 nous verrons ce résultat apparaitre :
Comme nous pouvons le constater, le package @angular/cli à correctement été ajouté à la liste des packages
globale à la version 6.0.8 qui est la version courante stable d’Angular
MAC
Ouvrir le fichier ainsi téléchargé et suivre les instructions en laissant toutes les valeurs par défaut.
Exécuter la commande suivante dans la console pour définir notre nom et l’email que nous utiliserons ensuite
pour créer notre compte gratuit sur GitHub:
Pour vérifier que tout va bien, relançons la console et tapons simplement git. Si l’installation a fonctionné, nous
devrions voir du texte en anglais expliquant l’utilisation de Git.
LINUX
Ouvrir le fichier ainsi téléchargé et suivre les instructions en laissant toutes les valeurs par défaut.
Ouvrir la console. (Si nous ne savons pas utiliser cette console, allons jeter un œil au rappel au début de ce
chapitre).
Exécuter la commande suivante pour définir notre nom et l’email que nous utiliserons ensuite pour créer notre
compte gratuit sur GitHub:
JULIEN HEROGUELLE 15
ANGULAR 4 Support V2.0
Pour vérifier que tout va bien, relancer la console et taper simplement git. Si l’installation a fonctionné, nous
devrions voir du texte en anglais expliquant l’utilisation de Git.
WINDOWS
Rendons-nous sur http://msysgit.github.io et télécharger la dernière version disponible. Une fois le fichier
récupéré, nous pouvons l'exécuter suivre les instructions. (nous pouvons laisser toutes les configurations par
défaut.). Cela va nous donner accès à Git ainsi qu’à une console émulant le comportement de Bash, la console
sous Linux.
Exécuter la commande suivante pour définir notre nom et l’email que nous utiliserons ensuite pour créer un
compte gratuit sur Github:
Pour vérifier que tout va bien, relançons la console et tapons simplement 'git'. Si l’installation a fonctionné, nous
devrions voir du texte en anglais expliquant l’utilisation de Git.
Petite astuce : utiliser la touche "Insert" de notre clavier pour coller du texte dans git bash (ctrl + v ne fonctionnera
sur Windows)
Nous avons enfin fini de mettre en place notre environnement, créons maintenant notre première application !
JULIEN HEROGUELLE 16
ANGULAR 4 Support V2.0
3 TYPESCRIPT
3.1 HISTORIQUE
TypeScript est un langage de programmation libre et open-source développé par Microsoft qui a pour but
d'améliorer et de sécuriser la production de code JavaScript.
C'est un sur-ensemble de JavaScript : C'est-à-dire que tout code JavaScript correct peut être utilisé avec
TypeScript.
Le code TypeScript est transpilé en JavaScript, pouvant ainsi être interprété par n'importe quel navigateur web
ou moteur JavaScript. Il a été co-créé par Anders Hejlsberg, principal inventeur de C#.
Il supporte la spécification ECMAScript 6 et permet un typage statique optionnel des variables et des
fonctions, la création de classes et d'interfaces, l'import de modules, tout en conservant l'approche non-
contraignante de JavaScript.
Pour plus d’informations voici le document émit par ECMA-Internationnal concernant les spécifications et le
fonctionnement de Javascript.
3.2 EN 5 MINUTES
Il n’est pas obligatoire d’installer TypeScript pour utiliser Angular, l’utilitaire CLI à une version du transpiler
TypeScript préinstallé. Mais nous allons quand même le faire pour pouvoir l’utiliser en dehors du Framework
Angular.
JULIEN HEROGUELLE 17
ANGULAR 4 Support V2.0
Puis, dans notre éditeur préféré, écrivons une fonction qui nous permettra de dire bonjour à une personne en
rentrant son nom dans une variable.
#greeter.ts
function greeter(person) {
return "Hello, " + person;
}
document.body.innerHTML = greeter(user);
Maintenant enregistrons ce fichier avec notre fameuse extension .ts par exemple greeter.ts
TRANSPILATION DU CODE
Nous avons utilisé une extension .ts mais ce que nous avons écrit n’est que du Javascript, nous pourrions
l’exécuter directement dans un navigateur à l’aide d’un fichier .js.
Nous voulons maintenant transpiler ce morceau de code TypeScript vers du JavaScript. Notez bien que je
n’ai pas parler de compilation. Le code en TypeScript que nous venons d’écrire ne passera jamais par l’étape
du binaire. Notre navigateur a besoin de JavaScript afin qu’il puisse l’interpréter correctement. C’est pour ça
que j’ai parlé de transpilation. Ce code TypeScript va tout simplement être traduit en langage Javascript afin
d’être compréhensible par le navigateur.
tsc greeter.ts
#greeter.js
function greeter(person) {
return "Hello, " + person;
}
document.body.innerHTML = greeter(user);
Si nous regardons à l’intérieur nous voyons que rien n’a changé. Ce fichier est une simple copie de notre
code TypeScript. Et c’est normal, notre code n’était ni plus ni moins que du Javascript, il n’y a pas de
conversion à faire.
JULIEN HEROGUELLE 18
ANGULAR 4 Support V2.0
TYPAGE
Ajoutons par exemple un type au paramètre que nous attendons dans cette fonction, nous voulons être sûr
que nous affichons bien une chaine de caractère. Sinon, nous voulons que TypeScript nous renvoie une
erreur.
#greeter.ts
document.body.innerHTML = greeter(user);
Les annotations de typage de TypeScript sont des manières simples de stipuler le type de retour d’une fonction,
d’une variable ou d’un paramètre. Dans notre cas, nous appelons la fonction avec un seul paramètre person de
type string.
Nous pouvons essayer de changer l’appel à la fonction afin de lui envoyer un entier.
#greeter.ts
let user = 1;
document.body.innerHTML = greeter(user);
5 document.body.innerHTML = greeter(user);
De manière similaire, si nous essayons de ne pas envoyer le paramètre à la fonction greeter, TypeScript vous
informera que la fonction est appelée avec un nombre inattendu de paramètre.
Dans les deux cas, TypeScript nous offre une analyse statique basée sur la structure du code, et le type de
l’annotation que nous fournissons
JULIEN HEROGUELLE 19
ANGULAR 4 Support V2.0
Notons que même s’il y a des erreurs, le fichier greeter.js est tout de même créé. Nous pouvons utiliser
TypeScript même s’il y a des erreurs dans notre code. Mais dans ce cas, TypeScript nous informe que notre
code ne va peut-être pas s‘exécuter de la manière attendue.
#greeter.js
function greeter(person) {
return "Hello, " + person;
}
var user = 1;
document.body.innerHTML = greeter(user);
INTERFACES
interface Person {
firstName: string;
lastName: string;
}
document.body.innerHTML = greeter(user);
Ici nous avons une interface qui décrit un objet qui a deux attributs, firstName et lastName. Dans TypeScript,
deux types sont comparables si leur structure interne est compatible. Ceci nous permet d’implémenter une
interface juste en renseignant la structure de l’interface requit, sans faire appel à Implements
Nous voyons que l’interface est bien implicite dans la transpilation vers Javascript. Il n’y a aucune trace de
l’interface que nous avons écrite plus haut. Elle sert seulement à TypeScript pour contrôler la logique de notre
code.
JULIEN HEROGUELLE 20
ANGULAR 4 Support V2.0
CLASSES
Pour finir, créons une classe Student avec un constructeur et quelques attributs publics.
Notons que les Classes et les Interfaces fonctionnent bien ensembles, laissant le programmeur décider du
bon niveau d’abstraction.
Également, nous pouvons utiliser public afin de spécifier les arguments du constructeur.
C’est un raccourci qui nous permet d’automatiquement ajouter des attributs à notre class.
Student {
firstName : String
middleInitial : String
lastName : String
Fullname : String
}
class Student {
fullName: string;
}
}
interface Person {
firstName: string;
lastName: string;
}
document.body.innerHTML = greeter(user);
Exécutons à nouveau notre commande favorite tsc greeter.ts et voyons le résultat en JavaScript :
JULIEN HEROGUELLE 21
ANGULAR 4 Support V2.0
Ce code parait quelques peu barbare, seulement, c’est un code particulièrement utilisé. Les classes dans
TypeScript sont juste des raccourcis pour de la POO basé sur les prototypes, fréquemment utilisé en Javascript.
Nous pouvons alors facilement constater que l’utilisation de TypeScript permet une approche beaucoup plus
claire, dans la lecture du code comme dans l’architecture de notre programme.
JULIEN HEROGUELLE 22
ANGULAR 4 Support V2.0
4 PREMIERE APPLICATION
Maintenant que nous avons vu quelques spécifications de TypeScript, nous pouvons d’ores et déjà commencer
à développer notre toute première application Angular.
ng new first-app
Nous voyons que la commande a créé un certain nombre de fichiers, parmi eux se trouvent :
JULIEN HEROGUELLE 23
ANGULAR 4 Support V2.0
Exécutons maintenant la commande qui va nous permettre de lancer notre application : ng serve –-open
Date: 2018-06-28T12:50:10.686Z
Hash: e8e3505bb172de5054c9
Time: 8917ms
chunk {main} main.js, main.js.map (main) 10.6 kB [initial] [rendered]
chunk {polyfills} polyfills.js, polyfills.js.map (polyfills) 227 kB [initial]
[rendered]
chunk {runtime} runtime.js, runtime.js.map (runtime) 5.22 kB [entry] [rendered]
chunk {styles} styles.js, styles.js.map (styles) 15.6 kB [initial] [rendered]
chunk {vendor} vendor.js, vendor.js.map (vendor) 3.07 MB [initial] [rendered]
i 「wdm」: Compiled successfully
JULIEN HEROGUELLE 24
ANGULAR 4 Support V2.0
LE DOSSIER SRC.
Notre application se trouve dans le dossier src/. Tous les components, templates, styles, images, et tout ce que
notre application a besoin va dans ce dossier. Tous les fichiers en dehors de ce répertoire vont aider à builder
notre application.
src
├── app
│ ├── app.component.css
│ ├── app.component.html
│ ├── app.component.spec.ts
│ ├── app.component.ts
│ └── app.module.ts
├── assets
│ └── .gitkeep
├── environments
│ ├── environment.prod.ts
│ └── environment.ts
├── browserslist
├── favicon.ico
├── index.html
├── karma.conf.js
├── main.ts
├── polyfills.ts
├── styles.css
├── test.ts
├── tsconfig.app.json
├── tsconfig.spec.json
└── tslint.json
Fichier Fonction
JULIEN HEROGUELLE 25
ANGULAR 4 Support V2.0
JULIEN HEROGUELLE 26
ANGULAR 4 Support V2.0
JULIEN HEROGUELLE 27
ANGULAR 4 Support V2.0
JULIEN HEROGUELLE 28
ANGULAR 4 Support V2.0
LE DOSSIER ROOT.
Le dossier src/ est juste un des éléments à l’intérieur du dossier root du projet.
first-app/
├── e2e
│ ├── src
│ │ ├── app.e2e-spec.ts
│ │ └── app.po.ts
│ ├── protractor.conf.js
│ └── tsconfig.e2e.json
├── node_modules/...
├── src/...
│ └── karma.conf.js
├── .editorconfig
├── .gitignore
├── .git
├── README.md
├── angular.json
├── package-lock.json
├── package.json
├── tsconfig.json
└── tslint.json
JULIEN HEROGUELLE 29
ANGULAR 4 Support V2.0
Fichier
Fonction
e2e/ À l’intérieur de e2e/ se trouvent les tests end-to-end. Ils ne doivent pas
être à l’intérieur du dossier src/ car les tests e2e doivent être séparés
des tests de l’application principale. C’est aussi pour cette raison qu’ils
ont leur propre fichier tsconfig.e2e.json.
node_modules/ Node.js créé ce dossier et range tous les modules tiers, listés dans
package.json à l’intérieur
.editorconfig Une configuration simple de notre éditeur, afin d’être sûr que tous le
monde utilise notre projet avec les mêmes configurations basiques.
Beaucoup d’éditeurs supportent le fichier .editorconfig. Voir
http://editorconfig.org pour plus d’informations.
.gitignore La configuration de Git pour être sûr que les fichiers auto-générés ne sont
pas commit vers la source.
angular.json Configuration pour Angular CLI. Dans ces fichiers nous pouvons mettre
différentes valeurs par default et aussi configurer quels fichiers sont inclus
quand notre projet quand il est builder. Voir la documentation officielle
pour en savoir plus.
package.json La configuration npm qui liste tous les packages tiers que notre projet
utilise. Nous pouvons aussi ajouter nos propres custom scripts ici.
JULIEN HEROGUELLE 30
ANGULAR 4 Support V2.0
README.md Documentation basique pour notre projet, pré-rempli avec les informations du
CLI.
Il faut mettre à jour ce fichier afin que n’importe qui puisse builder notre app !
tsconfig.json Configuration du compiler Typescript pour que notre IDE prenne et nous
mette à disposition des outils utiles
JULIEN HEROGUELLE 31
ANGULAR 4 Support V2.0
5 ARCHITECTURE
Nous savons déjà construire un module (notre application Angular est un module en soi).
...
app
│ ├── app.component.css
│ ├── app.component.html
│ ├── app.component.spec.ts
│ ├── app.component.ts
│ └── app.module.ts
...
Ceci illustre le but d’un NgModule qui est simplement celui de regrouper les composants et/ou services qui
vont ensemble. Rien de plus, rien de moins.
Nous pouvons donc les comparer à un package Java ou à un namespace en PHP ou C#.
Au minimum, nous créerons des modules de pages (sinon notre application sera vide). Les 2 autres types de
modules sont optionnels, mais nous allons vite en avoir besoin si nous voulons réutiliser et optimiser notre code.
JULIEN HEROGUELLE 32
ANGULAR 4 Support V2.0
MODULES DE PAGES
Les modules de pages sont les seuls types de modules qui nous intéresserons pour l’instant.
Ce sont des modules avec routing (c.à.d. qu’ils sont connectés par un chemin que l’utilisateur devra emprunter
pour avoir accès au module, ses composants et services). Ils servent à séparer et compartimenter les
composants de notre application.
Par exemple pour nos pages d’inscription, de connexion et de déconnexion, nous pourrions avoir un seul
AccountModule. Puis pour d’autres pages telles qu’une liste d’article, un article seul ou l’ajout et la suppression
d’un article, nous pourrions avoir un seul ArticleModule.
N’importe quel NgModule peut inclure un nombre infini de composants additionnels, ils peuvent être chargé par
le router ou bien appelé depuis le template. Les composants qui appartiennent au même NgModule partagent le
même contexte (c.à.d. qu’ils ont accès les uns aux autres).
Un composant contrôle une partie de l’écran appelé une vue (view), cette vue peut appeler d’autres
composants et leurs vues respectives et former ce que l’on appelle une hiérarchie de vues. Par exemple :
Ce système nous permet de définir arbitrairement des parties plus ou moins complexes de l’écran qui peuvent
être créés, modifiées ou bien détruites en tant qu’entité distincte du reste de l’application.
Quand nous créons un composant, il est directement associé à une seule vue, appelé la vue hôte (host view).
La vue hôte peut être la racine d’une autre succession de vue, qui elles-mêmes peuvent contenir d’autres vues
qui seront à leur tour la vue hôte d’autres composants. Ces composants peuvent être dans le même NgModule
ou bien importés depuis d’autres NgModules et emboités jusqu’à n’importe quelle profondeur.
JULIEN HEROGUELLE 33
ANGULAR 4 Support V2.0
<div class="auth-page">
<div>
<h1>{{ title }}</h1>
<p>
<a [routerLink]="['/login']" *ngIf="authType == 'register'">Have an account?</a>
<a [routerLink]="['/register']" *ngIf="authType == 'login'">Need an account?</a>
</p>
<app-list-errors [errors]="errors"></app-list-errors>
<form [formGroup]="authForm" (ngSubmit)="submitForm()">
<fieldset [disabled]="isSubmitting">
<fieldset>
<input
formControlName="username"
placeholder="Username"
type="text"
*ngIf="authType == 'register'" />
</fieldset>
<fieldset>
<input
formControlName="email"
placeholder="Email"
type="text" />
</fieldset>
<fieldset>
<input
formControlName="password"
placeholder="Password"
type="password" />
</fieldset>
<button [disabled]="!authForm.valid" type="submit">
{{ title }}
</button>
</fieldset>
</form>
</div>
</div>
Un template combine HTML et balises Angular qui peuvent modifier les éléments du HTML avant même qu’ils
soient affichés.
JULIEN HEROGUELLE 34
ANGULAR 4 Support V2.0
Grace à ces nouvelles notations, Angular nous offre tout un florilège de fonctionnalités qui nous permettrons de
synchroniser le template avec le component qui lui ai associé.
Il est ainsi possible de propager une donnée du component vers le DOM, du DOM vers le component et les deux
à la fois. Angular nomme ces fonctionnalités ainsi :
• Les Directives, apportes la logique de programmation à nos template, comme des structures
conditionnelles, des boucles, des changements dans le DOM sur les propriétés des éléments et encore
bien des choses ;
*ngIf="authType == 'register'"
• L’Interpolation connectent les données de notre application avec le DOM ;
<h1>{{ title }}</h1>
• Le Data Binding permet de modifier le DOM en fonction d’un modèle, si un changement est intervenu
sur ce dernier ;
• Le Property binding permet de mettre à jour le DOM à partir d’un modèle, si un changement est apporter
à une valeur de ce dernier ;
• L’Event binding est le fait que les actions de l’utilisateur permettent d’exécuter une fonction du
component associé suite à un évènement émis par un des éléments du DOM.
Avant qu’une vue ne soit affichée, Angular évalue les Directives et résout les Binding Markups (les annotations
qui nous permettent d’utiliser ces fonctionnalités) dans le template afin de modifier le HTML et le DOM selon la
logique de notre programme.
En résumé : Angular lit d’abord le template et remplace toutes les valeurs de nos interpolations ensuite il résout
les directives et envois une première version du html à notre utilisateur. Il va ensuite faire en sorte que les données
du DOM restent synchroniser avec les components tout en suivant la logique de notre programme. Traquant le
moindre évènement que l’utilisateur pourra envoyer à notre application.
JULIEN HEROGUELLE 35
ANGULAR 4 Support V2.0
Notre template pourra également utiliser des Pipes, qui améliorent l’expérience utilisateur par la transformation
de l’affichage des valeurs. Nous pourrons par exemple les utiliser afin d’afficher la date ou bien les valeurs
monétaires d’une manière appropriée à langue de l’utilisateur. Angular a déjà des fonctions pipes prédéfinies
mais nous pourront en créer de nouvelles.
Grace à tout ça, le template que nous avons plus haut peut être interprété en HTML et ressembler au final à ceci
:
<div class="auth-page">
<div>
<h1>Connexion</h1>
<p>
<a href="register" >Need an account?</a>
</p>
<ul>
Des erreurs sont survenues lors de la soumission du formulaire
<li>Mot de passe ou nom d'utilisateur incorrect</li>
</ul>
<form action="/">
<fieldset disabled="disabled">
<fieldset>
<input
formControlName="email"
placeholder="Email"
type="text" />
</fieldset>
<fieldset>
<input
formControlName="password"
placeholder="Password"
type="password" />
</fieldset>
<button disabled type="submit">
Connexion
</button>
</fieldset>
</form>
</div>
</div>
JULIEN HEROGUELLE 36
ANGULAR 4 Support V2.0
Ou bien à cela :
<div class="auth-page">
<div>
<h1>Inscription</h1>
<p>
<a [routerLink]="['/login']" *ngIf="authType == 'register'">Have an account?</a>
</p>
<ul>
Des erreurs sont survenues lors de la soumission du formulaire
<li>Veuillez renseigner un nom d'utilisateur visible par tous</li>
</ul>
<form action="/">
<fieldset disabled>
<fieldset>
<input
formControlName="username"
placeholder="Username"
type="text" />
</fieldset>
<fieldset>
<input
formControlName="email"
placeholder="Email"
type="text" />
</fieldset>
<fieldset>
<input
formControlName="password"
placeholder="Password"
type="password" />
</fieldset>
<button disabled type="submit">
Inscription
</button>
</fieldset>
</form>
</div>
</div>
JULIEN HEROGUELLE 37
ANGULAR 4 Support V2.0
En ce qui concerne les données et la logique qui ne sont pas associés avec une vue spécifique, et que nous
voulons partager entre nos composants, nous pouvons créer un Service.
Un service est une classe qui peut directement être injectée à l’intérieur d’un composant client en tant que
dépendance.
Les services et l’injection de dépendances nous permet de garder des composant qui ne réclament pas de
données au serveur, ne valident pas d’entrée d’utilisateur ou n’écrivent pas directement dans la console.
Ils délèguent toutes ces taches aux services.
ROUTING
Le Module Router d’Angular nous donne accès à un service qui nous permet de définir un chemin de navigation
à travers les différents états de notre application et la hiérarchie des vues.
Elle est construite autour des principes de base de la navigation sur le Web :
• Entrer une URL dans la barre d’adresse et le navigateur nous présente la page correspondante;
• Cliquer sur un lien dans la page et le navigateur nous dirige vers une nouvelle page;
• Cliquer sur la flèche de retour de notre navigateur va lire l’historique pour nous renvoyer à la dernière
page visitée.
Bien entendu, notre Router va renvoyer l’utilisateur vers des vues et non des pages.
Lorsqu’un utilisateur clique sur un lien ou bien entre l’url de votre site, Angular intercepte le comportement de
son navigateur et nous affiche la bonne hiérarchie de vue.
Nous parlons de lien cliquable ou bien d’url mais nous pouvons demander au Router d’attendre n’importe
quel stimulus venant de l’utilisateur comme cliquer sur un bouton, insérer un fichier ou copier un texte. Le
router inscrit toute l’activité dans l’historique du navigateur et donc navigation peut fonctionner correctement.
Pour définir ces chemins nous allons associer des routes à des composants en utilisant une syntaxe «URL
like» qui intègre les données de notre programme. Nous pouvons alors appliquer la logique de notre
programme afin de décider quelle vue peut être affiché ou non avec nos propres règles d’accès.
JULIEN HEROGUELLE 38
ANGULAR 4 Support V2.0
5.4 RECAPITULATIF
Les modules sont comparables à des namespaces, ils ne servent qu’à regrouper les services et les composants
dans le même contexte afin qu’ils aient accès les uns aux autres.
Un composant contrôle une partie de l’écran appelé une vue, il y en a une seule par composant. Forgée à
partir d’un template, cette vue peut appeler d’autres composants et leurs vues respectives et former ce que l’on
appelle une hiérarchie de vues. Un composant peut être créé, modifié ou supprimé dans la hiérarchie des vues
à la volée et de manière distincte du reste de l’application.
Les services regroupent la logique et les données communes à plusieurs composants. Ils permettent de
séparer la logique métier de l’interface utilisateur. Ils sont injectés en tant que dépendances dans chaque
composant qui en a besoin.
Le routeur est un module qui nous fournit un service qui va nous permettre de connecter plusieurs
hiérarchies de vues à l’aide d’URL. Nous pouvons ainsi faire naviguer l’utilisateur à travers notre
application, avec tous les avantage d’Angular, sans pour autant que l’utilisateur ne soit déstabilisé par rapport
à l’utilisation normale qu’il a de son navigateur (gestion de l’historique, retour en arrière ou en avant).
Mettons maintenant tout ça en pratique. Nous allons enrichir notre application test avec notre premier
composant.
JULIEN HEROGUELLE 39
ANGULAR 4 Support V2.0
L'application entière est rangée dans un module appelé AppModule et il en sera de même pour toutes nos futures
applications.
Le module principal est défini dans un fichier appelé app.module.ts à la racine du dossier app/.
// 1 Initialisation du module
@NgModule({
/* 2 Déclarations des components qui composent le module */
declarations: [
AppComponent
],
/* 3 Import des différents modules dont nous allons avoir besoin dans toute notre
application */
imports: [
BrowserModule
],
/* 4 Définition des services que nous allons utiliser. Ici nous ne déclarons pas
encore de service */
providers: [],
/* 5 Le module AppModule à besoin d'un composant à bootstraper, c.à.d qu'il a besoin
d'un composant autour duquel il va fonctionner et qu’il va afficher en premier, par
défaut Angular CLI en créé un, l’appelle AppComponent et l’assigne automatiquement */
bootstrap: [AppComponent]
})
export class AppModule { } //5 La class AppModule et son export
JULIEN HEROGUELLE 40
ANGULAR 4 Support V2.0
• (1) Il définit le module principal de notre application, appelé AppModule par convention.
• (2) Il déclare le component principal de notre application.
• (3) Il importe les différents modules dont nous allons avoir besoin dans toute notre application. (Ici
BrowserModule)
• (4) Il fournit les services communs à tous les modules de notre application.
• (5) Il indique à l’application qu’elle peut bootstraper sur notre AppComponent déclaré plus haut.
• Finalement JavaScript exporte notre class AppModule afin qu’elle soit accessible de l’extérieur.
Attention ! : Il faut bien noter que chacun de ces mots ont leur importance.
Dans notre fichier est écrit la définition du notre module principal. C’est une Classe nommée AppModule sur
laquelle est ajouté le décorateur @NgModule. Ce décorateur est un gros objet qui va se construire autour d’un
plus petit objet que nous allons lui fournir en premier argument. C’est ce dernier qui va définir le cœur de notre
component.
Dans cet objet nous indiquons que nous voulons que le module déclare les components qu’il veut regrouper.
Nous lui demandons d’importer une liste d’autre modules qui nous fourniront des services et des components
déjà développés pour nous et dont nous aurons besoin. Ensuite nous lui indiquons qu’il doit fournir une liste de
service aux components déclarés plus haut.
Le dernier attribut de cet objet est un cas particulier du module principal de n’importe quelle application Angular.
Lorsque nous définissons un module sur lequel l’application entière va se baser, nous avons besoin d’indiquer à
cette application un composant parent de tous les autres composants. Ce composant sera accompagné
d’une vue qui sera la première vue de notre hiérarchie de vue. Pour faire simple ce composant sera notre page
entière.
JULIEN HEROGUELLE 41
ANGULAR 4 Support V2.0
JULIEN HEROGUELLE 42
ANGULAR 4 Support V2.0
Rendons-nous une fois de plus à la racine du dossier app/ et ouvrons le fichier app.component.ts.
// Imports
import { Component } from '@angular/core';
Donc nous avons une Classe AppComponent sur laquelle est ajouté le décorateur @Component, même principe
que pour @NgModule ce décorateur attends un objet en seul argument. Dans cet objet nous indiquons que le
sélecteur de ce composant sera «app-root». C’est le nom que nous allons utiliser pour appeler ce component.
Dans le cas du component principal, son sélecteur est par convention «app-root». Il est appelé dans le fichier
index.html par ce nom.
Ensuite il est indiqué les URI relatifs jusqu’au template, qui est un fichier .html et jusqu’à la feuille de style qui
sera joint au template de manière totalement transparente pour nous.
Puis, nouvelle chose pour nous, un attribut est déclaré dans notre Class AppComponent. Notez juste sa
présence, nous verrons son utilité dans un instant.
JULIEN HEROGUELLE 43
ANGULAR 4 Support V2.0
Jetons maintenant un léger coup d’œil au template associé à ce composant. Il est situé dans le même répertoire
que notre fichier app.component.ts et se nomme app.component.html.
Voici donc le template associé à notre composant principal, c’est lui qui s’est affiché tout à l’heure lorsque notre
navigateur s’est ouvert.
Ce fichier est composé à 99% de HTML standard, donc rien de particulier mis à part l’annotation {{ title }}.
C’est en fait une référence à l’attribut title du component AppComponent. Lorsque notre composant va
interpréter le template, il va simplement remplacer ce qui se trouve entre {{}} par la valeur d’un attribut dont
nous aurons renseigné le nom et qui est disponible dans AppComponent.
JULIEN HEROGUELLE 44
ANGULAR 4 Support V2.0
Tous ce que nous avons vu jusqu’à présent ne nous a servi qu’à afficher un titre dont le dernier mot est la valeur
de l’attribut title de notre Class AppComponent.
Pour ce chapitre, imaginons que notre entreprise ait un client qui a décidé de développé une application qui
servira à lister les vinyles qui sont dans ses étagères.
Nous sommes en charge de créer le socle de l’application et de développé le composant de l’application qui
affichera un aperçu de la fiche d’un seul vinyle. Ce composant sera un élément d’une liste le plus souvent, ou
bien simplement un aperçu d’un vinyle.
Pour les besoins du développement, l’équipe s’est concerter à propos de la nomenclature et de l’architecture de
l’application et a décidé que le composant SingleVinylPreviewComponent devra se trouver dans le module
de page VinylModule. Dans ce module seront rangés tous les composants et services relatifs à l’affichage des
pages en rapport avec les vinyles.
Nous avons déjà mis en place le socle de notre application, ajoutons-y tous de suite le module VinylModule
puis un composant SingleVinylPreviewComponent.
Angular CLI fait ça très bien pour nous, nous n’aurons que deux commandes à taper.
Pas besoin d’options dans notre cas nous voulons simplement ajouter un nouveau module à notre application.
Tapons tout de suite cette commande dans la console à la racine de notre projet et voyons le résultat.
Angular nous a créé un dossier vinyl/ et deux fichiers contenant déjà quelque chose.
Le premier pèse 267 octets et est un fichier qui accompagne chaque module, service ou component et dont la
nomenclature terminera systématiquement par .spec.ts. C’est une base permettant d’écrire les tests
unitaires relatifs aux fichiers nouvellement créés. Nous nous y attarderons beaucoup plus loin dans la
formation, notez simplement qu’ils existent pour l’instant et qu’ils seront créés automatiquement à chaque
nouveau module, composant ou service.
JULIEN HEROGUELLE 45
ANGULAR 4 Support V2.0
Ce fichier est précédé donc logiquement par un deuxième fichier, qui lui est bien le fichier contenant le module
que nous voulions créer. Il s’appelle donc vinyl.module.ts.
Sans plus attendre ajoutons un composant à notre module. Pour des raisons de clarté, je vous propose d’installer
ce component dans un dossier components/ à l’intérieur du dossier vinyl/, car il y sera rangé avec tous les
autres éléments qui serviront à construire nos pages vinyles.
La commande de création de composant est tout à fait similaire à celle de création de module, elle se présente
sous la même forme : ng generate component chemin/depuis/app/nom-du-component –options
Notre composant sera donc rangé dans le dossier vinyl/ relatif à VinylModule, dans un dossier components/
et se nommera singleVinylPreview. Son chemin par rapport au dossier app/ sera donc /vinyl/pages/
singleVinylPreview.
Nous avons tous les éléments pour taper la commande. Voyez plutôt.
La commande nous retourne alors l’information qu’elle a bien créé un nouveau composant réparti en 4 fichiers
puis a mis à jour le fichier principal de notre VinylModule. Dans l’ordre l’utilitaire a créé :
Angular CLI à d’ailleurs déjà ajouté notre composant à la liste des composants déclarés dans notre module
VinylModule voyez plutôt le fichier vinyl.module.ts :
@NgModule({
imports: [
CommonModule
],
declarations: [SingleVinylPreviewComponent]
JULIEN HEROGUELLE 46
ANGULAR 4 Support V2.0
})
export class VinylModule { }
Il a importé la Classe de notre composant dans le fichier, puis l’a ajouté au tableau des déclarations. Notre
composant est alors accessible partout à l’intérieur de ce module.
Pour l’instant le module de routage n’est pas encore mis en place, nous nous en occuperons plus tard, ce n’est
pas notre travail actuellement. Cependant nous voulons quand même pouvoir interagir avec notre composant
afin de pouvoir tester le résultat de notre code.
Pour ce faire nous avons besoin que notre SingleVinylPreviewComponent soit accessible depuis le
composant principal de notre application qu’est AppComponent. Les modules ont la capacité de déclaré
des composants, d’importer des modules, mais également d’exporter des composants afin qu’ils deviennent
accessibles à travers le module qui les exportes. Dans le fichier vinyl.module.ts, ajoutons une ligne qui
indiquera à notre module qu’il faut qu’il export le composant SingleVinylPreviewComponent. Puis importons
le module VinylModule dans le module principal de notre application AppModule.
#vinyl.module.ts
...
@NgModule({
imports: [
CommonModule
],
declarations:[SingleVinylPreviewComponent],
exports:[SingleVinylPreviewComponent]
})
export class VinylModule { }
Puis :
#app.module.ts
...
import {VinylModule} from "./vinyl/vinyl.module";
...
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
VinylModule
],
...
Cette petite manipulation a rendu notre composant SingleVinylPreviewComponent accessible partout depuis
l’application.
Nous n’avons plus qu’à l’appeler dans notre template principal afin qu’il soit affiché.
JULIEN HEROGUELLE 47
ANGULAR 4 Support V2.0
Pour ce faire, une nouvelle balise nous a été rendu accessible par Angular lors de la déclaration du composant,
elle porte le nom du sélecteur de notre composant. Par défaut la nomenclature appliquée est alors app-nom-
du-composant, ici logiquement, ce serait app-single-vinyl-preview mais allons tous de même vérifier dans le
fichier single-vinyl-preview.component.ts à la ligne de la déclaration du sélecteur.
...
@Component({
selector: 'app-single-vinyl-preview',
templateUrl: './single-vinyl-preview.component.html',
styleUrls: ['./single-vinyl-preview.component.css']
})
...
La théorie étant bonne, nous n’avons plus qu’à supprimer le code du template par défaut en trop et ajouter
simplement notre balise <app-single-vinyl-preview>.
#app.component.html
<div style="text-align:center">
<h1>
Welcome to {{ title }}!
</h1>
</div>
<app-single-vinyl-preview></app-single-vinyl-preview>
Notre composant est bien affiché sur notre page d’accueil, nous allons maintenant pouvoir commencer à le
tester.
7.1 TEMPLATING
Tout d’abord ajoutons le minimum de css dont nous aurons besoin tout au long de cette application.
Nous allons faire ça très simplement grâce à Angular, NPM et toute la communauté qui entoure ces outils.
Pour faire simple et ne pas prendre de place dans notre projet minimaliste, nous allons utiliser un framework
css des plus simple, qui porte très bien son nom, j’ai nommé Mini.css. Peut-être avez-vous déjà entendu parler
de Bootstrap et bien Mini.css par du même principe. Il met en place un css et une grille déjà construite. La
JULIEN HEROGUELLE 48
ANGULAR 4 Support V2.0
différence est que Mini.css utilise au maximum les balises et attributs de base de HTML et CSS afin que
nous n’ayons pas à apprendre à l’utiliser.
Premièrement, ouvrons notre terminal à la racine notre application comme toujours. Puis nous allons taper une
commande que nous connaissons déjà, elle permet d’ajouter un module à la liste des packages NPM :
Resultat :
NPM nous retourne que le package s’est correctement installé, passons à l’étape suivante.
Il faut maintenant intégrer le nouveau css à notre application Angular. Pour ce faire, la démarche est très
simple. Nous devons ouvrir le fichier angular.json qui se trouve à la racine de notre projet puis nous rendre vers
les environs de la ligne 25 et ajouter le chemin vers la feuille de style du package nouvellement installer à la liste
des styles.
Comme nous le voyions tout à l’heure, NPM range tous les modules qu’il installe dans le répertoire
node_modules/. Ce répertoire est conjoint au fichier angular.json.
Notre package se trouve dans un dossier qui porte son nom. Et selon la documentation de Mini.css, le fichier
CSS à importer, se trouve dans le dossier dist/ et porte le nom de mini-default.css.
milligram/
├── examples/
│ └── index.html
├── dist/
│ ├── milligram.css
│ └── milligram.min.css
├── license
└── readme.md
Ajoutons ce chemin à la liste des fichiers style que notre application Angular va compiler avant d’envoyer le
template à nos utilisateurs.
#angular.json
...
"styles": [
"src/styles.css",
JULIEN HEROGUELLE 49
ANGULAR 4 Support V2.0
"node_modules/mini.css/dist/mini.default.css"
],
...
Relancer notre application avec ng serve. Le résultat devrait d’ores et déjà être visible.
L’INTERPOLATION
Nous l’avons vu plus haut nous pouvons faire pleins de choses très puissantes de manière très simple avec des
templates. Nous allons tout de suite passer en revue toutes les fonctionnalités qu’Angular nous offre et les
différentes façons de les appliqués.
L’interpolation est le premier outil mis à notre disposition pour que l’on puisse dynamiser nos templates. Grace
à l’interpolation nous pouvons afficher la valeur d’un attribut de la classe de notre component, directement dans
le template, toujours en gardant scrupuleusement cette valeur à jour dans le DOM en prenant en compte les
changements qui pourraient lui être apportés.
L’interpolation s’effectue en ajoutant les caractères {{ et }} autour du nom de l’attribut que l’on vise dans le
template.
Pour reprendre l’exemple que nous avions vue plus haut, reprenons notre SingleVinylPreviewComponent et
essayons d’afficher ce que pourrait être un vinyle à notre utilisateur.
Tout d’abord retournons dans notre component puis ajoutons notre objet vinyle et ses attributs.
Vinyl {
title : String
imageUrl : String
artiste : String
releaseYear : Number
}
Cet objet contient le titre du vinyle, l’url d’une photo de la pochette, le nom de l’artiste compositeur et l’année de
sortie du disque. Tous les attributs de cet objet seront des Strings pour l’instant, excepté l’attribut releaseYear
qui sera un Number.
JULIEN HEROGUELLE 50
ANGULAR 4 Support V2.0
#vinyl-list.component.ts
...
export class SingleVinylPreviewComponent implements OnInit {
constructor() { }
ngOnInit() {
}
Puis à l’intérieur de notre template faisons simplement référence à notre objet et ses attributs de cette manière :
{{ nomObjet.NomAttribut }}
Pour le reste nous allons tout simplement enrichir notre template avec du pur html ainsi que les classes de
Milligram, afin de mettre en forme l’affichage de notre vinyle.
#vinyl-list.component.html
<div class="card">
<div class="section media">
<img height="150" src="{{vinyl.imageUrl}}" alt="Album photo of {{vinyl.title}}" >
</div>
<div class="section">
<h3>{{vinyl.title}} <br><small>par {{vinyl.artiste}}</small></h3>
</div>
<div class="section" style="text-align: center">
<h5 class="bold">{{vinyl.releaseYear}}</h5>
</div>
</div>
Si vous enregistrez les modifications apportées aux fichiers et ouvrez votre navigateur, vous verrez
immédiatement le résultat.
JULIEN HEROGUELLE 51
ANGULAR 4 Support V2.0
Nous remarquons que toutes les valeurs que nous avions renseignés au component ont correctement été
interpolés à l’intérieur du template. Les attributs de type String s’affichent de la manière attendue, ainsi que
l’année de sortie, bien qu’étant un attribut de type Number, il a été Caster en String afin d’être convenablement
affichée.
L’interpolation est donc un très bon moyen pour synchroniser les données du component dans un template.
Angular va prendre les valeurs dans le composant et essaye de les interprété au mieux et même de les convertir
dans le bon type afin de les afficher. Et bien sûr tout ça en gardant toutes les valeurs à jour.
PROPERTY BINDING
Nous allons maintenant voire comment modifier les propriétés des éléments du DOM.
Grâce au property Binding, nous pouvons affecter la valeur d’une propriété d’un élément du DOM à la valeur
d’un attribut contenu dans le component. Cette technique est toujours du data binding one-way. Le component
va modifier la vue et non l’inverse.
Dans le premier cas, nous affectons la valeur de la propriété avec une interpolation. Souvenez-vous que
l’interpolation ne renvoie que des Strings au final, nous ne pouvons donc pas affecter de propriété avec
un Number ou un Boolean avec cette méthode.
La seconde méthode a été développée afin de pouvoir régler ce problème. Grâce à cette méthode nous pouvons
affecter n’importe quel type de variable primitif aux propriétés de nos éléments (String, Number, Boolean etc…).
Et même plus que ça, nous pouvons maintenant affecter une condition plutôt qu’un simple attribut. Notre balise
ressemblera donc à ça :
La propriété pourra alors prendre deux valeurs, True ou False, en fonction du résultat de la condition que nous
lui aurons donné. Vous ne voyez peut être pas l’intérêt tout de suite, mais imaginez que nous avons un formulaire
que nous ne voulons soumettre seulement si un champ est correctement rempli. Nous pourrions alors jouer sur
le property binding du bouton de soumission de formulaire, pour qu’il n’ait l’état « Enable » que lorsque nous
l’aurons décidé, tenez par exemple.
JULIEN HEROGUELLE 52
ANGULAR 4 Support V2.0
Dans ce cas, le bouton aura la propriété disabled, tant que la variable value sera null.
La méthode numéro 3 est une seconde façon de noter le Property Binding, plus en phase avec les normes
W3C, elle sera utilisée de manière préférentielle si l’accessibilité et le référencement fond partie des
problématiques de votre projet.
Nous avons déjà vue comment se passait le property binding sur un élément du DOM juste au-dessus.
Le Property Binding sur un attribute directive fonctionne de la même manière. Pour rappel, un attribute
directive est une directive modifiant le comportement ou l'apparence d'un élément. Angular propose déjà une
série d'attribute directives tels que ngClass ou ngStyle. Imaginons que l'on veuille changer la couleur du texte
de notre div à l'aide des styles CSS. Angular propose d'utiliser la directive ngStyle afin d'appliquer
dynamiquement un attribut de style CSS sur l'élément courant. Pour réaliser cette prouesse, la
directive ngStyle utilise le Property Binding. Nous pouvons donc nous créer une propriété couleur dans notre
component et appliquer cette couleur en tant que style CSS. Voilà comment nous l’écririons dans notre template :
Le Data Binding va remplacer la variable couleur dans le template par sa valeur définie dans le Component.
Nous n’avons qu’à modifier la notation de la propriété src de la balise image de notre vinyle.
Ceci parait un peu plus lisible. Voyons coté navigateur si notre solution fonctionne.
JULIEN HEROGUELLE 53
ANGULAR 4 Support V2.0
Rien n’a changé à première vue, c’est la preuve que cela fonctionne. Nous avons bien affecté l’attribue src de
l’image avec la bonne variable.
Nous allons maintenant voire ensemble comment fonctionne le Property Binding d’Angular grâce au décorateur
@Input.
Pour illustrer le property binding, je vous propose de passer l’objet vinyl à notre composant
SingleVinylPreviewComponent directement depuis notre component principal. Il s’agit d’un property binding
classique.
Tout d’abord, rendez-vous dans le component SingleVinylPreviewComponent afin de modifier notre attribut
vinyl.
#single-vinyl-preview.component.ts
...
@Input()
public vinyl: object;
Nous avons simplement effacé l’assignation à la variable vinyl pour enfin lui ajouter le décorateur @Input. Grâce
à ce dernier la variable vinyl de notre composant devient initialisable depuis l’exterieur. Plus précisément, au
moment d’appeler notre composant, je vais spécifier la variable que je veux qu’il utilise et ainsi au moment de
l’initialisation de notre composant, il aura accès à cette variable et pourra travailler dessus.
Regardez plutôt :
Dans notre composant principal ajouter un attribut mjVinyl à la classe de type objet, rigoureusement le même
que celui que nous venons d’effacer dans le composant SingleVinylPreview.
#app.component.ts
...
export class AppComponent {
title = 'Welcome to app!';
JULIEN HEROGUELLE 54
ANGULAR 4 Support V2.0
imageUrl: 'https://img-4.linternaute.com/PI-
AYLwdrSAlAsBVE53jZasrWYM=/350x/smart/4184ae2fdda74cb5b2e150bc98efebe8/ccmcms-
linternaute/19006.jpg',
releaseYear: 1987,
};
}
Puis dans le template du même component. Nous avons maintenant accès à la variable vinyl du composant
SingleVinylPreview. De la même manière que les autres Property binding, la référence à cette variable se fait
entre [] puis à droite se trouve notre nouvelle variable mjVinyl.
<h1 style="text-align:center">{{title}}</h1>
<div class="container">
<app-single-vinyl-preview [vinyl]="mjVinyl"></app-single-vinyl-preview>
</div>
Regardons le résultat.
Cela fonctionne. Grace au décorateur @Input, notre SingleVinylPreviewComponent affiche notre objet mjVinyl
sans problème.
EVENT BINDING
Avec le property binding nous avons appris à interagir sur le DOM avec notre component. Nous allons maintenant
voire comment interagir avec nos components à partir d’un élément du DOM. Par exemple, si nous prenons un
bouton, nous pouvons lui assigner une fonction à exécuter. Angular gère ce Data binding à partir
d’évènement, d’où le terme d’Event binding. Grace à ce mécanisme, nous allons pouvoir assigner des
fonctions à des évènements utilisateur. Comme le clique, la frappe sur le clavier etc… La syntaxe reste proche
du property binding :
<button (event)="myFunction()"></button>
<button on-event="myFunction()"></button>
À gauche de l’égalité nous retrouvons le nom de l’évènement entre parenthèses () ou bien précédé de -on
puis à droite, on trouve l’appelle à la fonction qui sera exécutée. Le component interceptera l’évènement sur
le bouton et exécutera immédiatement la fonction attendue.
JULIEN HEROGUELLE 55
ANGULAR 4 Support V2.0
Par exemple, disons que nous voulons ajouter un bouton à la fiche de notre vinyle, qui modifiera le nom de
l’artiste.
Ajoutons d’abord une fonction à notre component, qui modifiera l’attribut artiste de notre model.
#vinyl-list.component.ts
...
changeArtiste() {
this.vinyl.artiste = 'King of pop';
}
#vinyl-list.component.html
...
</ul>
<button (click)="changeArtiste()">Changer de nom</button>
</div>
Dans ce cas, nous avons bien un element du DOM qui modifie notre model.
Nous pouvons également créer nos prores Events Binding très simplement afin d’envoyer un évènement d’un
component vers son component parent. Pour illustrer, nous prendrons l’exemple d’un nouveau Component,
qui se chargera d’incrémenter ou de décrémenter une valeur à l’aide de deux boutons et d’envoyer le résultat
via un évènement. Son composant parent se chargera de récupérer cet évènement afin de changer le model
avec la sa valeur.
JULIEN HEROGUELLE 56
ANGULAR 4 Support V2.0
Pour cette exemple nous allons ajouter un nouveau module, afin d’y rangé les composant d’UI pouvant être
utilisé dans plusieurs Component. Puis nous ajouterons un nouveau component CountingButtonsComponent à
ce module.
#shared.module.ts
...
@NgModule({
imports: [
CommonModule
],
declarations: [CoutingButtonsComponent],
exports: [CoutingButtonsComponent]
})
export class SharedModule { }
On importe le module Shared dans le module où nous voulons utiliser notre component. Ici VinylModule.
#vinyl.module.ts
...
@NgModule({
imports: [
CommonModule,
SharedModule,
],
declarations: [SingleVinylPreviewComponent],
exports: [SingleVinylPreviewComponent]
})
export class VinylModule { }
Puis nous déclarons notre component dans le template où nous voulons l’afficher.
#single-vinyl-preview.html
...
<div class="section">
<app-couting-buttons></app-couting-buttons>
</div>
JULIEN HEROGUELLE 57
ANGULAR 4 Support V2.0
#couting-buttons.component.ts
...
export class CoutingButtonsComponent implements OnInit {
constructor() { }
ngOnInit() {
}
Lorsque @Input se charge de recevoir une valeur. @Output se chargera d’en émettre une. Ainsi, valueChange
est une instance de la classe EventEmitter. Cette classe nous offre un support afin d’émettre un évènement et
une valeur associé. Nous n’avons plus qu’à déclarer notre Event Binding dans le composant où nous voulons
nos boutons.
Écrivons une fonction afin de prendre en charge ce nouvel évènement dans notre composant
SingleVinylPreview. Je vous propose que l’on change l’année de sortie de notre vinyle, à l’aide de notre nouveau
composant. Nous initialiserons alors la valeur de notre compteur à l’année de sortie du disque et nous prendrons
la valeur que retourne l’évènement afin de l’assigner à notre model. Ça fait beaucoup d’explication mais cela se
fait en peu de lignes de code.
JULIEN HEROGUELLE 58
ANGULAR 4 Support V2.0
#single-vinyl-preview.ts
...
changeReleaseYear(value) {
this.vinyl.releaseYear = value;
}
#single-vinyl-preview.component.html
...
<div class="section">
<app-couting-buttons
(valueChange)="changeReleaseYear($event)"
[value]="vinyl.releaseYear" >
</app-couting-buttons>
</div>
TWO-WAY BINDING
Nous avons, avec cet exemple, déjà créé un Two-way binding. Et oui, notre composant modifie le model à l’aide
d’un évènement envoyé par le DOM ( c’est les boutons + et - ), puis le DOM est impacté en fonction de la
modification de notre model. ( c’est l’année qui change sur la fiche ). Le Two way binding c’est précisément ça,
notre composant travail en Input ET en Output. Angular a simplement confondu ces notations, afin de réduire
la taille du code que nous aurons à écrire. Pour ce faire, ils ont utilisé une combinaison des notations de Property
et d’Event Binding. L’appelle à notre composant binder va simplement changer.
JULIEN HEROGUELLE 59
ANGULAR 4 Support V2.0
<app-couting-buttons
(valueChange)="changeReleaseYear($event)"
[value]="vinyl.releaseYear" >
</app-couting-buttons>
<app-couting-buttons
[(value)]="vinyl.releaseYear" >
</app-couting-buttons>
Nous remarquons que nous avons évincé l’appelle à la fonction du component parent ChangeReleaseYear().
Elle ne nous est plus utile dès l’instant où nous avons choisi d’utiliser cette notation. Elle est totalement prise en
charge par Angular et se déroule maintenant en arrière-plan. Nous pouvons même l’effacée de notre Component.
#single-vinyl-preview.component.ts
...
ngOnInit() {
}
changeArtiste() {
this.vinyl.artiste = 'King of pop';
}
Retournons sur notre navigateur. Nous remarquons que le comportement de notre composant n’a pas changé.
Le Two-way binding nous à éviter d’écrire une nouvelle fonction générique, en rendant la déclaration au
component plus simple, sans avoir a changé un seul brin de code coté composant fils. Simple et efficace !
8 DIRECTIVES
Les directives sont des instructions intégrées dans le DOM que nous utiliserons presque systématiquement
lorsque nous créerons des applications. Lorsqu’Angular lit le template et voit une directive, il suit les instructions
qui correspondent à cette directive.
Nous pouvons créer nos propres directives, mais nous n’aborderons pas ce sujet dans ce cours, celui-ci relève
de techniques plus avancées. Néanmoins voici quelques liens si vous voulez vous renseigner sur le sujet :
http://www.learn-angular.fr/les-directives/
https://angular.io/guide/attribute-directives
https://www.tutorialspoint.com/angular4/angular4_directives.htm
Nous allons voir deux types de directives. Ce sont les principales. Les directives structurelles et celles par attribut.
Il existe un autre type de directive, les directives de composant. Ce sont elles qui sont en charge de l’instanciation
et de leur exécution durant le programme.
JULIEN HEROGUELLE 60
ANGULAR 4 Support V2.0
Les directives structurelles sont en charge (comme leur nom l’indique) de la structure du DOM, leurs rôles sont
de manipulé les éléments du DOM. Elles sont reconnaissables par un * les précédents. Nous allons en voir deux
pour l’instant même s’il en existe pas mal d’autres :
NGIF
Un élément du DOM auquel nous ajoutons la directe *ngIf=”condition” ne s’affichera que si la condition
renvoi un résultat Truthy (la valeur est égale à true ou bien la variable est définie et non nul). Comme une
structure conditionnel classique en somme.
Imaginons que nous voulons créer une fonction édition sur notre component SingleVinylPreview. Alors les
boutons que nous avons créés sur le template devraient s’afficher seulement si nous sommes en train d’’éditer
la fiche de notre vinyle. Développons tous de suite cette fonctionnalité.
Nous avons besoin d’une nouvelle variable isEditing à l’intérieur de notre component. Et d’une fonction qui va
faire passer sa valeur de true à false et inversement.
#single-vinyl-preview.component.ts
...
isEditing = false;
constructor() { }
ngOnInit() {
}
switchEditMode() {
this.isEditing = this.isEditing ? false : true;
}
...
Puis ajoutons la directive *ngIf à la div de nos boutons + et - et utilisons le bouton Modifier dans le but de
quitter le mode et de passer en mode edition.
JULIEN HEROGUELLE 61
ANGULAR 4 Support V2.0
</app-couting-buttons>
</div>
Tout se déroule comme nous l’avions prévu, nous voyons ici tout de suite l’intérêt de cette directive.
Passons tout de suite à l’exemple suivant afin d’illustrer la deuxième directive que nous allons étudier.
JULIEN HEROGUELLE 62
ANGULAR 4 Support V2.0
NGFOR
Nous n’allons pas garder notre application avec un seul vinyle indéfiniment, rajoutons quelques nouveaux
exemples à notre liste du vinyle. Pour ça, rangeons les dans un tableau à l’intérieur du component
AppComponent.
#app.component.ts
...
public vinyls: Array<object> = [{
title: 'Bad',
artiste: 'Michael Jackson',
imageUrl: 'https://img-4.linternaute.com/PI-
AYLwdrSAlAsBVE53jZasrWYM=/350x/smart/4184ae2fdda74cb5b2e150bc98efebe8/ccmcms-
linternaute/19006.jpg',
releaseYear: 1987,
}, {
title: 'Uprising',
artiste: 'Bob marley and the Wailers',
imageUrl: 'https://img.cdandlp.com/2017/06/imgL/118865816.jpg',
releaseYear: 1980,
}, {
title: 'Hendrix in the west',
artiste: 'Jimi Hendrix',
imageUrl: 'https://upload.wikimedia.org/wikipedia/en/9/9f/Hendrix_in_the_west.jpg',
releaseYear: 1972,
}, {
title: 'Porgy and Bess',
artiste: 'Louis Armstrong et Ella Fitzgerald',
imageUrl: 'https://media1.jpc.de/image/w600/front/0/8436542011464.jpg',
releaseYear: 1958,
}];
Ici vous notez l’utilisation du type Array<object>. Array est le type générique qui annonce que notre variable
sera un tableau. Quant aux notations <object> elles indiquent que ce tableau contiendra des variables de type
object. À droite de l’égalité nous instançons un tableau grâce aux [], puis à l’intérieur nos objets un par un
séparés par une virgule.
Revenons-en au template de ce même component et déclarons notre directive *ngFor sur notre component
SingleVinylPreviewComponent. Modifions légèrement notre template puis ajoutons notre
#app.component.html
...
<h1 style="text-align:center">{{title}}</h1>
<div class="container">
<div class="row">
<app-single-vinyl-preview *ngFor="let vinyl of vinyls" [vinyl]="vinyl"></app-
single-vinyl-preview>
</div>
</div>
Nous avons rajouté une div avec la class row, juste pour une question de mise en forme. Puis nous avons
déclaré la directive structurelle *ngFor=”let vinyl of vinyls”. Cette directive veut simplement dire :
JULIEN HEROGUELLE 63
ANGULAR 4 Support V2.0
« Nous instancons tous les objets vinyl du tableau vinyls et les nous les envoyons
dans le DOM. »
Le property binding suivant, [vinyl]=“vinyl”, envoie la variable nouvellement instancée vers notre
component SingleVinylPreview comme nous faisions avant.
Voyons le résultat :
Notre component se répète autant de fois qu’il y a d’objet dans notre tableau, et chaque objet est correctement
envoyé à son component. Nous pouvons également remarquer que chaque component est indépendant des
autres. Nous pouvons modifier la date sur chacun d’entre eux sans impacter le model voisin.
À la différence des directives structurelles, les directives par attribut se charge de modifier le comportement d’un
élément déjà existant dans le DOM. Comme pour les directives structurelles, il y a plusieurs directives par attribut.
Mais nous n’allons-nous intéresser seulement à deux exemples très utiles : ngStyle et ngClass, qui
permettent respectivement d’attribuer des styles ou bien des classes à nos éléments, toujours de manière
dynamique.
NGSTYLE
Cette directive permet d’ajouter ou d’enlever des styles à un element du DOM de manière dynamique. Elle attend
comme contenu un objet JS type clef-valeur. À gauche de sa déclaration se trouvera la clef du style à modifier
et à droite la valeur à laquelle nous voudrons mettre ce style.
Par exemple, imaginons que nous voulons qu’afin que l’utilisateur se repère un peu mieux sur notre application,
il ait un retour visuel du fait qu’il soit en train d’éditer la fiche d’un vinyle. Nous pourrions simplement ajouter une
directive ngStyle sur la couleur de notre date qui regardera la valeur de notre attribut isEditing, pour changer
de valeur en fonction du fait que nous soyons en train de l’éditer ou pas.
JULIEN HEROGUELLE 64
ANGULAR 4 Support V2.0
Au niveau du template, ajoutons simplement la directive ngStyle comme nous en avons parler juste plus haut.
À gauche de l’égalité nous avons le nom de la directive, puis à droite, un objet JS avec comme attribut la clef
color qui fait référence au style du même nom et qui sera égale à la valeur de retour de notre fonction
getDateColor
getDateColor() {
return this.isEditing ? 'green' : 'black';
}
Dans notre component, nous avons juste à ajouter cette fonction getDateColor qui renverra la bonne couleur
en fonction de la variable isEditing. Cette fonction retourne la valeur green si nous somme en cours d’édition,
black si ce n’est pas le cas.
NGCLASS
ngClass ne va pas seulement nous servir à modifier le style d’un élément, mais directement à lui appliquer
une ou plusieurs classes de style en fonction d’une condition.
Pour ce qui est de la notation elle fonctionne de la même manière que ngStyle. Elle attend un objet qui en clef
d’attribut attendra le nom de la classe qui nous intéresse puis comme valeur à cette clef la condition sous laquelle
cette classe doit être appliqué ou pas.
JULIEN HEROGUELLE 65
ANGULAR 4 Support V2.0
Exemple :
<div [ngClass]="{
'myClass': true,
'mySecondClass': variable == 'value'
}" />
Angular appliquera systématiquement la classe myClass à notre div, par contre il appliquera la classe
mySecondClass seulement si la variable variable est strictement égale à value.
9 PIPES
9 LE ROUTAGE
9.1 PRINCIPES
9.2 BASES
10 HTTP
10.2 INTERCEPTORS
11 RXJS
JULIEN HEROGUELLE 66