Angular Core
Angular Core
SOMMAIRE
Les outils
HTML5 et DOM
Web component
Premier projet
IoC/Injection de dépendances
Premier projet
Angular CLI
Templates + composants
Les pipes
Les services
Programmation réactive
Les Directives
Composant : Style et template
Formulaires et Binding Two Way
Bibliographie
Les outils
Les outils
Compiler :
• La compilation est le fait de traduire du code dans un langage A vers un langage B plus
bas niveau
– Exemple : Transformer du code en C++ vers du code machine
Transpiler :
• Transpiler transforme du code dans un langage vers un autre de même niveau.
– Exemple transformer la version de JavaScript ES6 vers la version ES5
4
Les outils : Git
Git :
• Gestionnaire de versions
• Permet de garder un historique des modifications
• Permet de mutualiser le développement d'un projet entre plusieurs développeurs
Serveur GIT
contenant
les fichiers
du projet
Chaque développeur peut modifier les fichiers du projet et ensuite le partager avec son
équipe en l'envoyant sur un serveur Git.
Chaque développeur doit avoir un "client Git" pour pouvoir se connecter au serveur. 5
Les outils : Node.js
Node.js :
• Est une plateforme applicative pour exécuter des applications en JavaScript
• Très utilisé dans le web pour faire des serveurs ou des outils pour aider les
développeurs.
• https://nodejs.org/en/
6
Les outils : npm
npm :
• Gestionnaire de paquet de Node.js
• Il permet de télécharger facilement des paquets (bibliothèques ou programmes)
Bibliothèque X Bibliothèque X
Projet Bibliothèque X Projet package.json Bibliothèque X
Bibliothèque X Bibliothèque X
Avant Après
Les gestionnaires de paquets gère les dépendances qui elles-mêmes peuvent dépendre
d'autres paquets.
Bibliothèque X Bibliothèque A
Bibliothèque A
Bibliothèque A
Bibliothèque A
Projet package.json Bibliothèque A
Bibliothèque Y Bibliothèque A
Bibliothèque A
Bibliothèque Z
bower contrairement à npm recroise les interdépendances, ce qui veut dire que si la
bibliothèques X et Y ont les mêmes dépendances, nous n'aurons pas de doublons.
Côté développement front-end, npm est utilisé pour les outils tandis que
bower pour les dépendances du projet car plus rapide pour installer les
dépendances. En développement serveur, npm est préférable.
8
Les outils : Gulp
gulp :
• Automatiseur de tâches
• Permet d'exécuter une série de commandes (tâches) selon des cas définis
9
Les outils : Yeoman
Yeoman :
• Générateur de projets
• Permet de créer la structure et mettre en place les outils pour l'ensemble d'un projet
web (back et front) et de le configurer pour qu'il soit exécutable immédiatement
L'outil est installé, il a besoin d'un fichier de configuration appelé générateur de projet :
http://yeoman.io/generators/
L'installation d'un générateur est généralement indiqué sur une page web
Exemple : http://fountainjs.io/
10
Les outils :
TSLint, ESLint, JSLint, JSHint :
• Analyseurs de code (TypScript, ES6, ES5)
• Donnent des indications sur le code source pour le rendre plus propre et maintenable
Babel :
• Transpileur ES6 ver ES5
Browsersync :
• Relance automatiquement le navigateur à chaque modification de l'application pour
afficher les changements.
Protractor :
• Permet de tester l'application Angular dans un navigateur en simulant un utilisateur
Jasmine :
• TDD : Permet de mettre en place des tests unitaires
11
HTML5 et DOM
HTML5 : Le DOM
Le DOM (Document Object Model) est une représentation d'un document sous forme
structuré, généralement sous forme d'arbre.
• Pour le navigateur, chaque balise est un objet avec des attributs et méthodes
• Les balises et valeurs sont appelés nœuds dans le DOM.
• Un nœud est appelé parent s'il a des nœuds descendants, ces derniers sont appelés
"nœuds enfants".
• Les nœuds du même parent sont frères.
13
HTML5 : Le DOM
Exemple de page HTML :
<html>
<head>
<meta charset="UTF-8">
<title>Titre de ma page</title>
</head>
<body>
<header></header>
<nav></nav>
<section>
<article>Texte de l'article 1</article>
<article>Texte de l'article 2</article>
<article>Texte de l'article 3</article>
</section>
<aside></aside>
<footer></footer>
</body>
</html>
14
HTML5 : Le DOM
Représentation du DOM de la page HTML :
Ces 4 éléments ne fonctionnent pas sur tous les navigateurs, il faut utiliser un polyfill.
Polyfill :
• Bibliothèque (js généralement) pour mettre à niveau la technologie d'un navigateur.
• Polymer et X-tag permettent l'intégration des Web Components
18
Web Component : Custom elements
Custom elements :
• Balises HTML5 personnalisées
• Doit contenir un tirer : <ma-balise></ma-balise>
document.body.appendChild(new BalisePersonnalisee());
19
Web Component : Shadow DOM
Shadow DOM :
• DOM encapsulé
• Contient son HTML, CSS et JS qui lui est propre
• Le CSS et le JS ne s'applique qu'à son HTML
• Le CSS/JS de la page ne s'applique pas sur lui ni celui des autres encapsulations
Page web
avec son HTML/CSS/JS
HTML/CSS/JS
Encapsulation dans le Shadow DOM
HTML/CSS/JS
20
Web Component : Template et HTML imports
Template :
• Balise HTML <template></template>
• La balise et son contenu ne sont pas affichés
• Les balises <script></script> et <img> à l'intérieur ne sont pas exécutées
• Sert de patron comme une classe
• Il doit être clone (sorte d'instanciation)
HTML imports :
• Possibilité d'importer du HTML dans du HTML comme un include en PHP, import en
JAVA, etc.
• <link rel="import" href="mon-fichier.html">.
21
Inversion de contrôle
et injection de dépendances
Inversion de contrôle
Inversion de contrôle :
• Ce n'est pas l'application qui contrôle l'ordre d'exécution de ses briques mais une entité
extérieure.
• Cela peut être un framework, un programme ou un utilisateur.
23
Inversion de contrôle
Inversion de contrôle :
• Nous pouvons comparer cela au conducteur avec sa voiture
Application Framework
Injection de dépendances :
• Type d'inversion de contrôle.
• Lorsqu'un élément N a besoin d'un élément B pour fonctionner, on le lui fournit.
Ce n'est donc pas la voiture qui gère les dépendances mais le conducteur.
25
Inversion de contrôle : Injection de dépendances
D
L'élément D a besoin d'autres éléments pour être utilisé.
3
1 2
Vérifier npm:
• Ouvrir une console et taper npm -v
Ajouter TypeScript :
• Installation : npm install -g typescript
• Initialiser le fichier de configuration du compilateur TypeScript :
tsc --init --target es5 --sourceMap --experimentalDecorators --emitDecoratorMetadata
Les commandes npm install -g n'ont plus besoin d'être retapés pour les futurs
projets.
-g indique une installation globale, donc pour tous les projets.
28
Installation
tsc a créé un fichier de configuration
• https://www.typescriptlang.org/docs/handbook/tsconfig-json.html
• https://www.typescriptlang.org/docs/handbook/compiler-options.html
Fichier tsconfig.json:
{
"compilerOptions": {
"target": "es5", // version cible de JavaScript (ES3 par défaut)
"experimentalDecorators": true, // accepte les décorateurs non standard
"emitDecoratorMetadata": true, // obligatoire pour l'option précédente
"sourceMap": true, // crée un fichier Map pour chaque fichier transpilé
"module": "commonjs", // permet l'utilisation de modules (require, export)
"noImplicitAny": false // les variables non typées ne seront plus des "any"
},
"exclude": [
"node_modules" // ne doit pas compiler ce qui se trouve dans ce répertoire
]
}
29
Installation
Initialiser le répertoire avec le fichier de configuration npm : npm init
• Un fichier package.json contenant les dépendances de notre projet est créé.
• https://docs.npmjs.com/
30
Mini projet : premier composant
Composant Angular :
• Brique Angular contenant du JS, HTML et CSS.
• Chacun des éléments de la brique sont "indépendants" du reste de l'application
Composant Angular
Style CSS
31
Mini projet : premier composant
Une page HTML peut ressembler à cela :
Composant
Composant Composant
Composant
Composant
Composant
Composant
Composant
Composant
32
Mini projet : premier composant
Premier composant :
premier.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'premier-composant',
template: '<h1>Mon premier composant</h1>'
})
Module
Sous Module A
Composant 1 Composant 2
Contrôlleur Contrôlleur
JS JS
Sous Module B
Template Template
HTML HTML
Style CSS Style CSS
Service
34
Mini projet : premier module
Création du module racine :
app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { PremierComponent } from './app.component';
@NgModule({
imports: [BrowserModule],
declarations: [PremierComponent], BrowserModule ne peut être
bootstrap: [PremierComponent] inclus que dans le module
}) principal sinon il faut utiliser
CommonModule
export class AppModule {
}
35
Mini projet : Script d'exécution
main.ts
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app.module';
platformBrowserDynamic().bootstrapModule(AppModule);
36
Mini projet : premier module
Schéma simplifié d'une application qui sera lancé par Angular :
Application
37
Mini projet : Configuration SystemJS
Configuration de SystemJS:
index.js
// configuration de SystemJS
System.config({
// mapping des dépendances
map: {
'@angular/core': 'node_modules/@angular/core/bundles/core.umd.js',
'@angular/common': 'node_modules/@angular/common/bundles/common.umd.js',
'@angular/compiler': 'node_modules/@angular/compiler/bundles/compiler.umd.js',
'@angular/platform-browser': 'node_modules/@angular/platform-
browser/bundles/platform-browser.umd.js',
'@angular/platform-browser-dynamic': 'node_modules/@angular/platform-browser-
dynamic/bundles/platform-browser-dynamic.umd.js',
'rxjs': 'node_modules/rxjs'
},
packages: {
// '.' tous les packages -> les modules serons chargés sans suffixe ".js"
// SystemJS ajoutera l'extension automatiquement
'.': {},
}
});
// démarrage de notre application
System.import('main');
38
Mini projet : Création template
Fichier index.html : premier.component.ts
import { Component } from '@angular/core';
@Component({
Index.html selector: 'premier-composant',
template: '<h1>Mon premier composant</h1>'
<!DOCTYPE html> })
<html> export class PremierComponent {
<head> }
<meta charset="UTF-8">
<title>Titre de mon application</title>
</head>
<body>
<premier-composant> Chargement d'Angular… </premier-composant>
</body>
</html>
index.html en-tête
<head>
<meta charset="UTF-8">
<title>Titre de mon application</title>
<script src="node_modules/zone.js/dist/zone.js"></script>
<script src="node_modules/reflect-metadata/Reflect.js"></script>
<script src="node_modules/systemjs/dist/system.js"></script>
<script src="index.js"></script>
</head>
Élément commande
Component ng g component my-new-component
Directive ng g directive my-new-directive
Pipe ng g pipe my-new-pipe
Service ng g service my-new-service
Class ng g class my-new-class
Interface ng g interface my-new-interface
Enum ng g enum my-new-enum
Module ng g module my-module 42
Angular CLI
43
Templates
Templates
Rappel :
• Pour appeler un composant dans une page html, il suffit d'utiliser le selecteur comme
balise
• Le composant va insérer son template dans la balise correspondant au sélécteur.
page.html Composant
1
selector: " bal-comp"
<bal-comp></bal-comp>
Template
2 <div>Coucou</div>
Insertion du template
dans la baliste
Controller
45
Templates : fichier séparé
Composant avec template séparé :
app.component.ts
import { Component } from '@angular/core';
@Component({
selector: app-comp',
templateUrl: './app.component.html'
})
46
Templates : Afficher des valeurs
Afficher des valeurs depuis le contrôleur :
app.component.ts
import { Component } from '@angular/core';
@Component({
selector: app-comp',
templateUrl: './app.component.html'
}) app.component.html
<h1>Bonjour<h1>
export class PremierComponent {
etudiants: number = 322; <p> il y a {{etudiants}} élèves</p>
dir:any = { prenom: 'Adrien' }; <p> le directeur se nomme : {{dir.prenom}}</p>
}
Résultat de app.component.html
<h1>Bonjour<h1>
{{expression}}
interpolation
<h1>….
[propriété]="expression" {
One Way Binding }
[(ngModel)]="propriété"
Two Way Binding
48
Templates : Binding One Way
L'interpolation est un raccourcis d'écriture pour ce Binding One Way de l'attribut textContent
49
Templates : Binding One Way
50
Templates : Binding One Way
Binding One Way :
• Permet d'écrire dans n'importe que attribut d'un élément du DOM
Composant
{
title: string = "titre";
imageUrl: string = " mon-image.jpg"
}
En JavaScript les événements sont par exemple : clic souris, souris qui vient de bouger,
touche du clavier appuyé etc.
Ces événements peuvent être écoutés, et lorsqu'ils se produisent, exécuter une action
grâce à des fonctions.
exemple.html template_angular.html
<h1 onclick="alert('coucou');"> Salut </h1> <h1 (click)="afficheMessage('coucou')">Bonjour<h1>
composant.ts
…
export class MonComponent{
afficheMessage(message: string): void {
alert("mon message: " +message);
}
}
52
Templates : Evénements
Fonctionnement d'un événement en Angular :
• Basé sur le patron de conception Observateur (voir Bibliographie)
• Les événements en Angular sont dit bouillonant
• "bouillonnant" (bubbling up) indique que l'événement se propage vers son parent, qui
lui-même le transmet à sont parent, etc.
template_angular.html
<div (click)="afficheMessage('parent')">
Message parent
<span (click)="afficheMessage('enfant')">Message enfant</span>
</div>
affiche
Message parent Message enfant
body
div
span
Clique souris
54
Templates : Evénements (bubble up)
Bouillonnement :
• Possible d'arrêter la transmission
Lors d'un événement, un objet est fabriqué, celui-ci contient l'information sur
l'événement.
composant.ts
Objet event envoyé
…
export class MonComponent{
afficheMessage(message: string, event:any): void {
alert("mon message: " +message); Action par défaut et
event.preventDefault(); boullonnement
event.stopPropagation(); arrêté
}
} 55
Templates : expression et instructions
56
Templates : variables locales
template.html
<h1 #monTitre>Bonjour</h1>
{{monTitre.textContent}}
57
Templates : balise template
template.html
<template> Ne sera pas
<ul> affiché
<li>message</li>
<li>message</li>
<li>message</li>
</ul>
</template>
58
Templates : Directives
Les directives :
• Sorte de composant sans template
• Permet de modifier le comportement des balises (donc de l'affichage d'un template)
ngIf : est une directive qui se comporte comme une condition "if"
template.html
Les balises contenues
<template [ngIf]="8 > 1">
dans le bloc
<ul> s'afficheront que si la
<li>message</li> condition est vraie
<li>message</li>
<li>message</li>
</ul>
</template>
composant.ts template.html
Écriture raccourcie :
• Ajouter une étoile * devant la directive et retirer la balise template
template.html
<ul *ngIf="8 > 1"> >
<li>message</li>
<li>message</li>
<li>message</li>
</ul>
60
Templates : Directives
composant.ts
ngFor :
• Boucle de type foreach …
export class MonComponent{
quantites: number[] = [12, 189, 17, 12];
}
template.html
affiche
<ul> 12
<li *ngFor="let valeur of quantites">{{valeur}}</li> 189
</ul> 17
12
template.html
Affichage de l'indice
<ul>
<li *ngFor="let valeur of quantites; let indice=index " >{{indice}} {{valeur}}</li>
</ul> affiche
0 12
1 189
Index est une variable fournie par ngFor, il en existe d'autres 2 17
3 12 61
Templates : Directives
ngSwitch :
• Condition switch
• Permet la sélection d'un template selon une valeur reçue
composant.ts
…
export class MonComponent{
position : number= 2;
}
template.html
<div [ngSwitch]="position">
<p *ngSwitchCase="1">Premier</p>
<p *ngSwitchCase="2">Second</p> affiche
<p *ngSwitchDefault>Pas dans les premiers</p> Second
</div>
Templates : Directives
ngStyle :
• Permet de modifier les propriétés CSS d'un élément
template.html
<div [ngStyle]="{ color: 'red', fontWeight: 'bold' }">Texte en rouge et gras</div>
ngClass :
• Permet de modifier les classes d'un élément
template.html
<div [ngClass]="{'une-classe': true, 'une-autre': false}">
div avec des classes dynamiques
</div>
En inspectant l'élément dans le navigateur, celui-ci aura la
classe : "une-classe"
Les pipes
Les pipes: introduction
Pipe :
• Anciennement filtre en AngularJS
• Le nom provient de sa syntaxe utilisant le caractère pipe |
65
Les pipes: exemple
lowercase :
• Retire les majuscules d'un texte
template.html composant.ts
{{message | lowercase }} …
export class MonComponent{
message: string= "mon TEXTE à modifier";
}
uppercase :
• Tous les caractères sont passés en majuscule
66
Les pipes : avec paramètres
Pipes:
• Il est possible de fournir des arguments
Slice :
• Permet de découper une collection ou une chaîne de caractères
template.html affiche
{{ [2,9,10] | slice:0:1 }} 2
Le premier paramètre '0' est le point de départ de ce qui va être gardé et '1' celui d'arrivée
67
Les pipes : création
Pour créer un pipe:
• Implémenter PipeTransform, interface dans @angular/core
✓ La méthode à implémenter est : transform(value: any, ...args: any[]): any;
• Utiliser le décorateur @Pipe en fournissant le nom du pipe a utiliser
getchar.pipe.ts
import { PipeTransform, Pipe } from '@angular/core';
getchar.pipe.ts
import { PipeTransform, Pipe } from '@angular/core';
template affiche
{{'mon text' | getchar:2}} n
69
Les services
Les services
Service :
• Objet qui peut être utilisé un peu n'importe où
• Angular les fournit lorsqu'une classe en a besoin (injection)
• Ce sont des singletons, ce qui veut dire que l'objet n'existe qu'en un seul exemplaire
• Si nous enregistrons des valeurs dans un singleton, elles seront partagées
Composant_A 1 Instance
2
qui a besoin de ServiceMachin ServiceMachin
pour fonctionner 3 {
Angular attributs…
Composant_B 4 méthodes…
qui a besoin de ServiceMachin }
pour fonctionner 5
71
Les services : création
Service : exemple.service.ts
export class ExempleService {
constructor() {
}
uneMethode() {
console.log("Méthode de mon service");
}
} mon.component.ts
import { Component} from '@angular/core';
import { ExempleService } from '/chemin/exemple.service';
exemple.service.ts
import { Injectable } from '@angular/core';
import { UnAutreService } from '/chemin/unautre.service';
@Injectable()
export class ExempleService {
constructor(autre: UnAutreService) {
autre.action();
}
}
73
Les services : Dans le framework
L'objet Injector (qui est un service) reçoit un token "LeService" qui correspond à une classe.
Un Composant
export class MonComponent { Injection
constructor(exServ: LeService) { 5 Le composant a besoin de LeService
exServ.uneMethode(); 1
} Regarde s'il le
} trouve et
4 Injector 2 comment le
Ajouté dans un configurer
registre pour une
utilisation ultérieure Instance de Provider
LeService
Retourne l'instance
3
74
Les services : Provider
Provider : fournisseur (généralement de services)
Renommer le token (nom du service) pour qu'il soit différent de celui de la classe :
@NgModule({
providers: [
{ provide: "NouveauNom", useClass: ExempleService }
]
})
providers: [
{ provide: "UNE_CONSTANTE", useValue: "Salut !"}
]
75
Les services : Provider
providers: [
{
provide: ExempleService
useFactory: function() {
let texte: string = "coucou";
let service = new ExempleService();
service.message = texte;
return service;
}
}
]
76
Les services : Provider
Factory avec dépendance :
• Il est possible de récupérer un autre service ou une valeur définit dans les providers
providers: [
{ provide: "UNE_CONSTANTE", useValue: "Salut !"},
{
provide: ExempleService,
useFactory: function(UNE_CONSTANTE) {
let texte: string = UNE_CONSTANTE;
let service = new ExempleService();
service.message = texte;
return service;
},
deps: ["UNE_CONSTANTE"]
}
]
77
Les services : Provider
@Component({
selector: 'app-article',
templateUrl: './article.component.html',
providers: [
{ provide: ExempleService}
]
})
78
Les services : Provider
79
Programmation réactive
Programmation réactive
2
observable
Vas y ! L'action est exécutée
Objet A action
81
Programmation réactive
action
action
action
Vas y !
action
82
Programmation réactive
Observable :
• Objet qui va récupérer l'événement et lancer des actions
Quelques méthodes :
• map(fn) : applique une fonction fn à chaque événement et retourne la valeur
• filter(condition) : laisse passer l'événement sur la condition est vraie
• subscribe(fn) : exécute une fonction fn à chaque événement
83
Programmation réactive
RxJS
• Bibliothèque pour faire de la programmation réactive
• Documentation : https://github.com/Reactive-Extensions/RxJS
• Choisit par Angular
• On retrouve des bibliothèques équivalente pour la plupart des langages
exemple
import { Component, EventEmitter } from '@angular/core';
…
export class AppComponent {
constructor {
let obs = new EventEmitter();
let subscribe = obs.subscribe (
value => console.log(value),
error => console.log(error),
() => console.log('fin')
);
Directive :
• Brique d'Angular qui va interagir avec le template
Une directive utilise un sélecteur CSS pour indiquer son point d'activation
• Possibilité d'utiliser une combinaison CSS : div.titre (div ayant une classe titre)
87
Les directives : création
Exemple :
color.directive.ts
import { Directive } from '@angular/core';
Template.html
<div atcolor="{{proprieteComposant}}" colors="{{'Rouge' | lowercase}}"></div>
90
Les directives : création avec entrées
Nouvelle écriture (plus simple):
color.directive.ts
import { Directive, Input } from '@angular/core';
@Directive({
selector: '[atcolor]'
})
91
Les directives : Modification de balise
Directive et balise :
• La directive peut modifier la balise qui l'appel
• Nous importons ElementRef qui permet de travailler directement avec les Elements DOM
color.directive.ts
import { Directive, Input, ElementRef } from '@angular/core';
1
@Directive({
selector: '[atcolor]' Template.html
})
<h2 colors="red" atcolor > mon texte</h2>
export class ColorDirective { 2
el: ElementRef; 1 – L'attribut atcolor indique qu'il
constructor(el: ElementRef) { faut exécuter cette directive
3
this.el = el;
} 2 – Lors de la création de la
@Input() directive, Angular fournit
set colors(value) { l'élément DOM qui l'a appelé
this.el.nativeElement.style.backgroundColor = value;
} 3 – Angular trouve l'attribut colors
4 et fournit sa valeur au setter
}
4 – Changement de couleur de
l'élément. 92
Les directives : Cycle de vie
Bind de valeurs :
• Il est possible de lier la valeur d'un attribut DOM à un de la directive
composant.ts
…
color.directive.ts export class MonComponent{
Chargement de la
attributComposant : string= 'red';
… valeur
3
}
export class ColorDirective {
1
Template.html
@input() colors: string
constructor() { <div [colors]="attributComposant" atcolor ></div>
console.log(this.colors)
}
2 Instanciation de la directive
}
93
Les directives : Cycle de vie
Cycle de vie :
• Le cycle de vie d'une directive passe par des appels de méthodes bien définie
Les méthodes sont appelés par Angular à certains moments lors du fonctionnement de la
directive après son instanciation.
95
Les directives : Provider
Les directives tout comme les modules et les composants peuvent avoir leur propre
provider
96
Composant : Style et template
Composant : Style et template
Les directives et composants sont très proches
98
Composant : Encapsulation du style
Le CSS d'un composant a 3 niveaux d'encapsulations
99
Formulaires et Binding Two Way
Formulaires :
101
Formulaires : Pilotage template
Pilotage par template :
• Ajouter le module : FormsModule
Configuration du module
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';
@NgModule({ composant.ts
imports: [BrowserModule, FormsModule], @Component({
declarations: [AppComponent], selector: 'app-form',
bootstrap: [AppComponent] templateUrl: './form.component.html',
}) styleUrls: ['./form.component.css']
})
export class FormComponent {
constructor() { }
register(value) {
console.log("soumission", value);
}
}
102
Formulaires : Pilotage template
Form dans un
template est une Capture de l'événement "submit" du
formulaire et transmission à la méthode
directive
template.html "register" du composant
<form (ngSubmit)="register()">
<div>
<label>Login</label>
<input name="login" ngModel>
</div>
<div>
<label>Password</label>
<input type="password" name="password" ngModel>
</div>
<button type="submit">Envoyer</button>
</form>
Les champs à remplir avec l'attribut ngModel vont créer des objets FormControl contenant
les informations du champ.
1 - Lors de l'utilisation de ngForm dans un formulaire, la directive form la remplace par une
référence à FormGroup
adrien adrien
●●●●●● secret
106
Formulaires : Pilotage par le code
Formulaire piloté par le code :
• Plus verbeux mais apportant plus de possibilité
FormControl :
• Classe représentant un champ à remplir
Attribut Description
valid true si la valeur est correcte
errors liste des erreurs (objet)
dirty true si l'utilisateur modifie le champ
pristine false si l'utilisateur modifie le champ
touched true si l'utilisateur atteint le champ
untouched false si l'utilisateur atteint le champ
value valeur du champ
utilisation valueChanges Observable pour les changements de valeur
const password = new FormControl();
const login = new FormControl("adrien");
composant.ts
import { Component } from '@angular/core';
import { FormBuilder, FormGroup } from '@angular/forms';
@Component({
selector: 'register-comp',
templateUrl: 'register.component.html'
})
Injection par Angular de FormBuilder
export class FormComponent {
userForm: FormGroup;
register() {
console.log(this.userForm.value);
}
module.ts }
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
@NgModule({
declarations: [FormComponent],
imports: [FormsModule, ReactiveFormsModule ],
})
export class UnModule { }
110
Formulaires : Pilotage par le code
Lier le formulaire et le composant :
formGroup / formControlName :
• directives de ReactiveFormsModule
• Permet de lier des champs aux FormControl d'un FormGroup
111
Formulaires : Validation par code
Validation pour un formulaire piloté par le code :
• Classe Validator
Contrainte Description
Validators.required La valeur ne doit pas être vide
Validators.minLength(n) La valeur doit faire n caractères
Validators.maxLength(n) La valeur ne doit pas dépasser n caractères
Validators.pattern(p) La valeur doit respecter une regex
112
Formulaires : Validation par code
Validation pour un formulaire piloté par le code :
composant.ts
import { Component } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
@Component({ … })
export class FormComponent {
userForm: FormGroup;
constructor(fb: FormBuilder) {
this.userForm = fb.group({
login: fb.control( "", [ Validators.required, Validators.minLength(5) ]),
password: fb.control( "", Validators.required)
});
}
register() {
console.log(this.userForm.valid);
}
}
113
Formulaires : Validation par template
Validation pour un formulaire piloté par le template :
template.html
<form (ngSubmit)="register(userForm.value)" #userForm="ngForm">
<button type="submit">Envoyer</button>
</form>
114
Formulaires : Validateur personnalisée
Validateur personnalisé :
• Fonction recevant en paramètre un objet FormControl
• Retourne un objet {nomErreur: boolean} en cas d'erreur
• Retourne null si la valeur passe la validation
composant.ts
const majeur = (fc: FormControl) => {
return fc.value>=18 ? null : {mineur: true};
}
115
Requêtes HTTP
Requête HTTP :
Requête HTTP :
• Utilisation du module HttpModule pour faire les requêtes
• C'est le service Http qui fournit le requétage Ajax
module.ts
import { NgModule } from '@angular/core';
import { HttpModule } from '@angular/http';
@NgModule({ composant.ts
imports: [HttpModule] @Component({ … })
})
export class AppModule { export class PonyRacerAppComponent {
} constructor(http: Http) {
}
}
117
Requête HTTP :
Méthode Description
get Demander une ressource au serveur (exemple: un fichier, une page html,
un flux JSON, etc.)
Généralement en tapant une adresse ou en suivant un lien.
post Créer une ressource
put Ajout ou modification d'une ressource
delete Supprimer une ressource sur le serveur
head Demande d'information sur une ressource.
patch Modification d'une ressource
118
Requête HTTP :
Les méthodes de requêtage du service Http retourne un Observable.
Exemple
constructor(http: Http) {
http.get("https://na14.salesforce.com/services/data/")
.subscribe( (response) => {
console.log(response.status); // code http
console.log(response.headers); // en-tête
console.log(response.json() ); // corps
});
Pour envoyer des données, cela doit être sous forme de chaîne de caractères :
• http.post("url", JSON.stringify({ nom:adrien }) )
119
Requête HTTP :
Attribut Description
method méthode HTTP
headers objet de type Headers du module @angular/http
body information a envoyer
url url de la requête
search Ajoute des paramètres de recherche à l'url
withCredentials Booléen (requête contenant des habilitations)
responseType Le type de format attendu en retour
120
Requête HTTP :
Exemple :
Exemple
constructor(http: Http) {
http.request("https://na14.salesforce.com/services/data/", options)
.subscribe( (response) => {
console.log(response.status); // code http
console.log(response.headers); // en-tête
console.log(response.text() ); // corps
});
}
121
Les routes
Les routes
Les routes :
• Angular est un framework mono-pagé, il simule donc le changement de page
• Selont l'URL, Angular fera le lien avec la page à afficher
• Le module RouterModule est en version 3.0 contrairement aux autres qui sont en 2
• Il est responsable du futur passage d'Angular de la version 2 à 4 pour aligner les versions
123
Les routes : création
Il est conseillé de mettre les routes dans un fichier séparé.
Nous fabriquons un tableau de type Routes contenant la liste des "urls -> composant"
@NgModule({
imports: [BrowserModule, RouterModule.forRoot(ROUTES)],
declarations: [AppComponent, HomeComponent, FilmComponent],
bootstrap: [AppComponent]
})
app.component.html
<header>
<span>En-tête du site</span> En-tête du site
</header>
<main>
<router-outlet></router-outlet> Le corps, qui sera l'élément qui
</main> changera d'une url à l'autre
<footer>
<span>pied de page</span>
pied de page
</footer>
126
Les routes : création
Résultat qui sera attendu :
Template de : Template de :
HomeComponent FilmComponent
127
Navigation
Navigation dans le template :
• Lien menant d'une page à l'autre
128
Navigation : URL avec paramètres
URL avec paramètres :
• URL dynamiques
• Aller sur la page du film dont l'id est 18 : monsite.com/film/18
129
Navigation : URL avec paramètres
URL avec paramètre:
• Le composant d'une route peur récupérer par injection ActivatedRoute qui contient les
informations sur la route
• Utile pour récupérer les paramètres dynamiques
composant.ts
export class FilmComponent implements OnInit {
constructor(private route: ActivatedRoute) {
}
ngOnInit() {
const id = this.route.snapshot.params["filmId"];
}
}
130
Navigation : URL avec paramètres
URL avec paramètre:
• Il est possible de s'abonner à un observable à chaque changement de paramètres
composant.ts
export class FilmComponent implements OnInit {
constructor(private route: ActivatedRoute) {
}
ngOnInit() {
this.route.params.subscribe(params => {
console.log("changement des paramètres", params);
});
}
}
131
Les routes : page 404
Mettre en place la page 404 :
Arborescence :
Application
/films/search
/films/search/results
133
Les routes : Les routes imbriquées
Les routes imbriquées :
• Permettent de garder les éléments des templates des pages ascendantes
Template de :
Template de : FilmsSearchComponent
FilmsSearchComponent
pied de page
Template de :
FilmsResultsComponent
pied de page
pied de page
134
Les routes : Les routes imbriquées
Configuration des routes imbriquées :
app.routes.ts : contient la configuration des routes
export const ROUTES: Routes = [
{ path: "", component: HomeComponent },
{
path: 'films',
component: FilmsComponent,
children: [
{
path: 'search',
component: FilmsSearchComponent,
children: [
{
path: results',
component: FilmsResultsComponent
}
]
}
]
}
]; 135
Les routes : Les routes imbriquées
Templates des composantes imbriqués
films.component.html
<h2>Template des films</h2>
<router-outlet></router-outlet>
films.search.component.html
<h2>Template des recherches</h2>
<router-outlet></router-outlet>
films.results.component.html
<h2>Template des résultats</h2>
136
Les tests
Les tests
138
Les tests unitaires
Mocks :
• Objets factices utilisés pour les tests unitaires
• Permet de remplacer et de simuler des fonctionnalités dont dépendent la cible du test
Jasmine :
• Framework Behavior-driven development (BDD) pour les tests
BDD :
• Méthode de test base sur des scénarios (Et si… Dans le cas…)
• Utilisation d'outils pour reprendre les scénarios et appliquer les comportements
• Utilisation de mocks pour les fonctionnalités manquantes pour le test
Initialise l'environnement
avant de lancer les tests. foo.spec.ts
Évite de répéter le même describe("Tests sur la classe Foo", () => {
code pour chaque test let foo: Foo;
beforeEach( () => {
foo = new Foo(35, "adrien");
Test 1 });
Il existe afterEach qui s'exécute après les tests. Peut servir à refermer un flux.
141
Les tests unitaires
Élements de tests
Dummy (fantôme): Objet ou fonction qui ne fait que remplacer un autre pour les tests. Ne
fait rien.
Stub (bouchon) : Fake le plus simple possible. Contient des valeurs prédéfinies.
Mock (simulacre) : Objet généré par un outil de test à partir de la classe qu'elle doit
remplacer. On peut le configurer pour modifier son comportement lors des tests.
Spy (espions) : Mock qui surveille des appels sur des éléments
142
Les tests unitaires
foo.spec.ts
describe("Tests sur la classe Foo", () => {
let foo: Foo;
La méthode a
Espion beforeEach( () => { été appelé ?
foo = new Foo(35, "adrien");
spyOn(foo, "isPlusVieux").and.returnValue(true);
});
La méthode a dû
it("test methode isPlusVieux", () => { être appelé avec
pony. isPlusVieux(20); la valeur 20
expect(foo.isPlusVieux).toHaveBeenCalled();
expect(foo.isPlusVieux).toHaveBeenCalledWith(20);
});
});
143
Les tests unitaires
Il est possible d'utiliser l'injection de dépendances d'Angular pour les tests :
144
Les tests unitaires
Tester un service asynchrone :
145
Bibliographie
Bibliographie
https://angular.io/docs/js/latest/
https://nodejs.org/en/docs/
npm
https://docs.npmjs.com/
Angular CLI
https://github.com/angular/angular-cli
zone.js
https://blog.thoughtram.io/angular/2016/01/22/understanding-zones.html
@types/core-js
http://definitelytyped.org/
TS déclaration
https://www.typescriptlang.org/docs/handbook/declaration-files/introduction.html
TS Fichier de définitions
https://typescript.codeplex.com/wikipage?title=Writing%20Definition%20%28.d.ts%29%20Files
Patron de conception Observateur :
https://fr.wikipedia.org/wiki/Observateur_(patron_de_conception)
http://www.dofactory.com/javascript/observer-design-pattern
https://en.wikibooks.org/wiki/Computer_Science_Design_Patterns/Observer
147
Bibliographie
RxJS :
https://github.com/Reactive-Extensions/RxJS : code
https://xgrommx.github.io/rx-book/index.html : livre
Cycle de vie :
https://angular.io/docs/ts/latest/guide/lifecycle-hooks.html
https://embed.plnkr.co/?show=preview
Polymer :
https://www.polymer-project.org/1.0/
X-TAG :
http://x-tag.github.io/
ES6 et les navigateurs :
https://kangax.github.io/compat-table/es6/
Karma :
https://www.grafikart.fr/formations/javascript-unit-test/karma
http://javamind-fr.blogspot.fr/2015/01/karma-lexecuteur-de-tests-javascript.html
Un livre gratuit :
https://www.gitbook.com/book/rangle-io/ngcourse2/details
Livre pas gratuit :
https://www.packtpub.com/web-development/mastering-typescript
https://www.packtpub.com/web-development/learning-angular-2 148