Vous êtes sur la page 1sur 77

Angular : interaction entre composant

Achref El Mouelhi

Docteur de l’université d’Aix-Marseille


Chercheur en programmation par contrainte (IA)
Ingénieur en génie logiciel

elmouelhi.achref@gmail.com

H & H: Research and Training 1 / 61


Plan

1 Introduction
2 Balise d’interaction
3 Décorateurs d’interaction
Exemple avec @Input()
Exemple avec @ViewChild()
Exemple avec @ViewChildren()
Exemple avec @ContentChild()
Exemple avec @ContentChildren()
Exemple avec @Output()
4 Variable locale et @ViewChild
5 Service, subject et interaction

H & H: Research and Training 2 / 61


Introduction

Angular

Premières formes d’interaction


H I ©
Une application Angular est composéeU deE L composants
plusieurs
O on peut envoyer des
Mliens,
L
Eà un autre
En utilisant des formulaires et
f
des
r e
données d’un composant
ch
© A

H & H: Research and Training 3 / 61


Introduction

Autres formes d’interaction : parent-enfant

Ajouter le sélecteur d’un premier composant dans le template d’un


deuxième composant
on appelle le premier composant : composant fils
on appelle le deuxième composant : composant parent
H I ©
EL
Définir le sens de transmission de données par

M OU
un composant web Angular : ng-content

f E L @Output(), @ViewChild,
des décorateurs @Input(),
e
chr @ContentChild, @ContentChildren
@ViewChildren,

© A

H & H: Research and Training 4 / 61


Introduction

Autres formes d’interaction : parent-enfant

Ajouter le sélecteur d’un premier composant dans le template d’un


deuxième composant
on appelle le premier composant : composant fils
on appelle le deuxième composant : composant parent
H I ©
EL
Définir le sens de transmission de données par

M OU
un composant web Angular : ng-content

f E L @Output(), @ViewChild,
des décorateurs @Input(),
e
chr @ContentChild, @ContentChildren
@ViewChildren,

© A
Autres formes d’interaction : enfant-enfant ou parent-enfant

Le sélecteur du premier composant et celui du deuxième se trouvent


au même niveau ⇒ même parent : solution (Subject et Service)
H & H: Research and Training 4 / 61
Balise d’interaction

Angular

Avant de commencer
H I ©
Créons deux composants pere et fils
UEL
O
f E LM
Définissions une route /pere pour le composant pere

r e
Ajoutons le sélecteur du composant fils app-fils dans
ch
©A
pere.component.html

H & H: Research and Training 5 / 61


Balise d’interaction

Angular
Le fichier fils.component.ts

import { Component, OnInit } from ’@angular/core’;

@Component({
selector: ’app-fils’,
templateUrl: ’./fils.component.html’,
styleUrls: [’./fils.component.css’]
H I ©
})
UEL
export class FilsComponent implements OnInit {
O
constructor() { }
f E LM
ngOnInit() { }
ch r e
}
©A
Le fichier fils.component.html

<li>
Je suis un fils
</li>

H & H: Research and Training 6 / 61


Balise d’interaction

Angular
Le fichier pere.component.ts

import { Component, OnInit } from ’@angular/core’;

@Component({
selector: ’app-pere’,
templateUrl: ’./pere.component.html’,
styleUrls: [’./pere.component.css’]
H I ©
})
UEL
export class PereComponent implements OnInit {
O
constructor() { }
f E LM
ngOnInit() { }
ch r e
©A
}

Dans pere.component.html, on définit trois fils

<ul>
<app-fils></app-fils>
<app-fils></app-fils>
<app-fils></app-fils>
</ul>

H & H: Research and Training 7 / 61


Balise d’interaction

Angular
Et si on veut passer du contenu texte à notre composant enfant, on fait :
<ul>
<app-fils>John Wick</app-fils>
<app-fils>Jack Shephard</app-fils>
<app-fils>James Ford</app-fils>
H I ©
EL
</ul>

O U
f E LM
ch r e
©A

H & H: Research and Training 8 / 61


Balise d’interaction

Angular
Et si on veut passer du contenu texte à notre composant enfant, on fait :
<ul>
<app-fils>John Wick</app-fils>
<app-fils>Jack Shephard</app-fils>
<app-fils>James Ford</app-fils>
H I ©
EL
</ul>

O U
f E LM
En testant le résultat est :
ch r e
©A
Je suis un fils

Je suis un fils

Je suis un fils

Le contenu ajouté par le père n’apparaı̂t pas.


H & H: Research and Training 8 / 61
Balise d’interaction

Angular

Pour que le composant fils puisse récupérer le contenu défini par


le parent, on utilise la balise ng-content
<li>
Je suis un fils : <ng-content></ng-content>
H I ©
</li>
UEL
O
f E LM
ch r e
©A

H & H: Research and Training 9 / 61


Balise d’interaction

Angular

Pour que le composant fils puisse récupérer le contenu défini par


le parent, on utilise la balise ng-content
<li>
Je suis un fils : <ng-content></ng-content>
H I ©
</li>
UEL
O
f E LM
r
h:
cest e
A
En testant le résultat
©
Je suis un fils : John Wick
Je suis un fils : Jack Shephard
Je suis un fils : James Ford

H & H: Research and Training 9 / 61


Balise d’interaction

Angular

Remarque

H I
La balise ng-content a un attribut select qui prend comme valeur ©
UEL
O
le nom d’un attribut de n’importe quelle balise définie dans le
composant parent
f E LM
le nom d’une classe CSS
ch r e
©A
le nom d’une balise

H & H: Research and Training 10 / 61


Balise d’interaction

Dans pere.component.html, on définit le nom et le prénom dans deux balises ayant


deux attributs différents : prenomContent et nomContent
<ul>
<app-fils>
<span prenomContent> John </span>
<span nomContent> Wick </span>
</app-fils>
<app-fils>
<span prenomContent> Jack </span>
H I ©
EL
<span nomContent> Shephard </span>
</app-fils>
<app-fils>
O U
<span prenomContent> James </span>
<span nomContent> Ford </span>
f E LM
</app-fils>
ch r e
©A
</ul>

H & H: Research and Training 11 / 61


Balise d’interaction

Dans pere.component.html, on définit le nom et le prénom dans deux balises ayant


deux attributs différents : prenomContent et nomContent
<ul>
<app-fils>
<span prenomContent> John </span>
<span nomContent> Wick </span>
</app-fils>
<app-fils>
<span prenomContent> Jack </span>
H I ©
EL
<span nomContent> Shephard </span>
</app-fils>
<app-fils>
O U
<span prenomContent> James </span>
<span nomContent> Ford </span>
f E LM
</app-fils>
ch r e
©A
</ul>

Dans fils.component.html, on sélectionne les données selon les deux attributs


prenomContent et nomContent
<li>
Je suis un fils : mon nom est <ng-content select="[nomContent]"></ng-
content>
et mon prénom est <ng-content select="[prenomContent]"></ng-content>
</li>
H & H: Research and Training 11 / 61
Balise d’interaction

Angular

En testant le résultat est :


H I ©
Je suis un fils : mon nom est Wick et monE
U L est John
prénom
Je suis un fils : mon nom estL MO et mon prénom est Jack
r e f E Shephard
Je suis un fils :c
A h nom est Ford et mon prénom est James
mon
©

H & H: Research and Training 12 / 61


Balise d’interaction

Dans pere.component.html, on peut aussi définir des classes dont la valeur est soit
prenomContent ou nomContent
<ul>
<app-fils>
<span class=prenomContent> John </span>
<span class=nomContent> Wick </span>
</app-fils>
<app-fils>
<span class=prenomContent> Jack </span>
H I ©
EL
<span class=nomContent> Shephard </span>
</app-fils>
<app-fils>
O U
<span class=prenomContent> James </span>

f E
<span class=nomContent> Ford </span> LM
</app-fils>
ch r e
©A
</ul>

H & H: Research and Training 13 / 61


Balise d’interaction

Dans pere.component.html, on peut aussi définir des classes dont la valeur est soit
prenomContent ou nomContent
<ul>
<app-fils>
<span class=prenomContent> John </span>
<span class=nomContent> Wick </span>
</app-fils>
<app-fils>
<span class=prenomContent> Jack </span>
H I ©
EL
<span class=nomContent> Shephard </span>
</app-fils>
<app-fils>
O U
<span class=prenomContent> James </span>

f E
<span class=nomContent> Ford </span> LM
</app-fils>
ch r e
©A
</ul>

Dans fils.component.html, on sélectionne les données selon leurs classes


<li>
Je suis un fils : mon nom est <ng-content select=".nomContent"></ng-
content>
et mon prénom est <ng-content select=".prenomContent"></ng-content>
</li>
H & H: Research and Training 13 / 61
Balise d’interaction

Angular

En testant le résultat est le même


H I ©
Je suis un fils : mon nom est Wick et monE
U L est John
prénom
Je suis un fils : mon nom estL MO et mon prénom est Jack
r e f E Shephard
Je suis un fils :c
A h nom est Ford et mon prénom est James
mon
©

H & H: Research and Training 14 / 61


Balise d’interaction

Dans pere.component.html, on peut aussi utiliser plusieurs balises différentes

<ul>
<app-fils>
<span> John Wick </span>
<a href="#"> link </a>
</app-fils>
<app-fils>
<span> Jack Shephard </span>
<a href="#"> link </a>
H I ©
</app-fils>
UEL
<app-fils>
O
LM
<span> James Ford </span>
<a href="#"> link </a>
</app-fils>
r e f E
</ul>
ch
©A

H & H: Research and Training 15 / 61


Balise d’interaction

Dans pere.component.html, on peut aussi utiliser plusieurs balises différentes

<ul>
<app-fils>
<span> John Wick </span>
<a href="#"> link </a>
</app-fils>
<app-fils>
<span> Jack Shephard </span>
<a href="#"> link </a>
H I ©
</app-fils>
UEL
<app-fils>
O
LM
<span> James Ford </span>
<a href="#"> link </a>
</app-fils>
r e f E
</ul>
ch
©A
Dans fils.component.html, on sélectionne les données selon les balises

<li>
Nom et prénom : <ng-content select="span"></ng-content>,
pour apprendre plus => <ng-content select="a"></ng-content>
</li>

H & H: Research and Training 15 / 61


Balise d’interaction

Angular

En testant le résultat est :


H I ©
U ELplus => link
Nom et prénom : John Wick , pour apprendre
O apprendre plus => link
M, pour
E L
Nom et prénom : Jack Shephard
f
Nom et prénomc:h r e
James Ford , pour apprendre plus => link
© A

H & H: Research and Training 16 / 61


Décorateurs d’interaction

Angular

Décorateurs disponibles pour l’interaction entre composants

@Input() : permet à un composant fils de récupérer des


données de son composant parent
H I ©
UEL
O
@ViewChild() : permet à un composant parent de récupérer les
données de son composant enfant
f E LM
ch r e
@ViewChildren() : permet à un composant parent de
©A
récupérer les données de ses composants enfants
@Output() : permet à un composant parent de récupérer des
données de son composant enfant

H & H: Research and Training 17 / 61


Décorateurs d’interaction Exemple avec @Input()

Angular

H I ©
Dans cet exemple
U EL
O
LM
On définit dans fils.component.ts deux attributs ordre et
f E
villeNaissance qui seront affichés dans le template.
r e
ch
©A

H & H: Research and Training 18 / 61


Décorateurs d’interaction Exemple avec @Input()

Nouveau contenu de fils.component.ts

import { Component, OnInit, Input } from ’@angular/core’;

@Component({
selector: ’app-fils’,
templateUrl: ’./fils.component.html’,
styleUrls: [’./fils.component.css’]
})
export class FilsComponent implements OnInit {
H I ©
EL
@Input() ordre = ’’;
@Input() villeNaissance = ’’;
O U
constructor() { }
f E LM
ngOnInit() { }
ch r e
©A
}

Modifions le fichier fils.component.html

<li>
Je suis le {{ ordre }} fils et suis de {{ villeNaissance }}
</li>

H & H: Research and Training 19 / 61


Décorateurs d’interaction Exemple avec @Input()

Le fichier pere.component.ts
import { Component, OnInit } from ’@angular/core’;
import { FilsComponent } from ’../fils/fils.component’;

@Component({
selector: ’app-pere’,
templateUrl: ’./pere.component.html’,
styleUrls: [’./pere.component.css’]
})
H I ©
EL
export class PereComponent implements OnInit {
tab: Array<string> = [’premier’, ’deuxième’, ’troisième’];
nord = ’Lille’;
O U
sud = ’Marseille’;
capitale = ’Paris’;
f E LM
constructor() { }
ch r e
}
ngOnInit() { }
©A
Le fichier pere.component.html
<ul>
<app-fils [ordre]="tab[0]" [villeNaissance]="sud"></app-fils>
<app-fils [ordre]="tab[1]" [villeNaissance]="nord"></app-fils>
<app-fils [ordre]="tab[2]" [villeNaissance]="capitale"></app-fils>
</ul>
H & H: Research and Training 20 / 61
Décorateurs d’interaction Exemple avec @Input()

Angular

Le résultat est
H I ©
U
Je suis le premier fils et suis EdeL Marseille
L MetOsuis de Lille
r e f E
Je suis le deuxième fils
Je suis le c
A h
troisième fils et suis de Paris
©

H & H: Research and Training 21 / 61


Décorateurs d’interaction Exemple avec @Input()

Angular

Quelques interfaces prédéfinis dans Angular


H I ©
OnInit avec une méthode ngOnInit()E
U L utilise pour
qu’on
initialiser le composant
L MO
OnChange avec unee
r E ngOnChanges() qu’on utilise pour
mféthode
A ch de valeurs d’un fils
détecter les changement
©

H & H: Research and Training 22 / 61


Décorateurs d’interaction Exemple avec @Input()

Nouveau contenu de fils.component.ts


import { Component, OnInit, Input, OnChanges } from ’@angular/core’;

@Component({
selector: ’app-fils’,
templateUrl: ’./fils.component.html’,
styleUrls: [’./fils.component.css’]
})
export class FilsComponent implements OnInit, OnChanges {
H I ©
EL
@Input() ordre: string;
@Input() villeNaissance: string;
constructor() { }
O U
ngOnInit() { }

f E LM
ch r e
ngOnChanges(changes: SimpleChanges): void { console.log(changes); }

©A
}

H & H: Research and Training 23 / 61


Décorateurs d’interaction Exemple avec @Input()

Nouveau contenu de fils.component.ts


import { Component, OnInit, Input, OnChanges } from ’@angular/core’;

@Component({
selector: ’app-fils’,
templateUrl: ’./fils.component.html’,
styleUrls: [’./fils.component.css’]
})
export class FilsComponent implements OnInit, OnChanges {
H I ©
EL
@Input() ordre: string;
@Input() villeNaissance: string;
constructor() { }
O U
ngOnInit() { }

f E LM
ch r e
ngOnChanges(changes: SimpleChanges): void { console.log(changes); }

©A
}

Remarque

SimpleChanges est un objet JavaScript dont les clés sont les attributs changés et les
valeurs sont des objets SimpleChange

SimpleChange est un objet JavaScript contenant trois clés : previousValue,


currentValue et firstChange() ;

H & H: Research and Training 23 / 61


Décorateurs d’interaction Exemple avec @Input()

Pour afficher tous les changements

import { Component, OnInit, Input, OnChanges } from ’@angular/core’;

@Component({
selector: ’app-fils’,
templateUrl: ’./fils.component.html’,
styleUrls: [’./fils.component.css’]
})
export class FilsComponent implements OnInit, OnChanges {
H I ©
EL
@Input() ordre: string;
@Input() villeNaissance: string;
O U
LM
constructor() { }
ngOnInit() { }

r e f E
ch
ngOnChanges(changes: SimpleChanges): void {

©A
for (const key of Object.keys(changes)) {
console.log(key);
const obj = changes[key];
for (const cle of Object.keys(obj)) {
console.log(cle, obj[cle]);
}
}
}
}

H & H: Research and Training 24 / 61


Décorateurs d’interaction Exemple avec @Input()

Angular

Exercice
Dans pere.component.html, ajoutez deux input : un premier
pour nom et un deuxième pour ville

H I ©
EL
Dans pere.component.ts, définissez deux variables nom et un

OU
deuxième pour la ville et deux tableaux noms et villes
M
Créez autant de app-fils L
e f E que d’éléments dans noms (ou
villes)
A c hr
Chaque© fils récupère et affiche les valeurs envoyées par le
composant pere
L’utilisateur pourra ajouter un nombre indéterminé de composant
fils dans pere.

H & H: Research and Training 25 / 61


Décorateurs d’interaction Exemple avec @Input()

Angular

Exercice list-item
Créons deux composants list et item.
Chaque composant item reçoit le texte et sa couleur d’affichage
H I ©
EL
du composant list.

O U
Dans le composant list, on a deux zones de saisie : la première
E LM
pour le texte, la deuxième pour la couleur du texte à afficher (à
f
saisir en anglais).
ch r e
©A
En cliquant sur le bouton ajouter du composant list, un
nouveau composant item s’ajoute (s’affiche) au composant (dans
la page) avec la couleur indiquée par l’utilisateur.
L’utilisateur pourra ajouter un nombre indéterminé de texte.

H & H: Research and Training 26 / 61


Décorateurs d’interaction Exemple avec @ViewChild()

Angular

Objectif

Récupérer les données du premier composant fils à partir d’un


composant parent
H I ©
U EL
O
f E LM
ch r e
©A

H & H: Research and Training 27 / 61


Décorateurs d’interaction Exemple avec @ViewChild()

Angular

Objectif

Récupérer les données du premier composant fils à partir d’un


composant parent
H I ©
U EL
O
f E LM
Comment ?
ch r e
©A
Déclarer un composant fils comme attribut d’un composant parent
et le décorer avec @ViewChild()
Utiliser cet attribut pour récupérer les données souhaitées

H & H: Research and Training 27 / 61


Décorateurs d’interaction Exemple avec @ViewChild()

Angular
Commençons par déclarer le composant fils comme attribut dans pere.component.ts et
le décorer avec @ViewChild()
import { Component, OnInit, ViewChild } from ’@angular/core’;
import { FilsComponent } from ’../fils/fils.component’;

@Component({
selector: ’app-pere’,
H I ©
templateUrl: ’./pere.component.html’,
styleUrls: [’./pere.component.css’]
U EL
O
LM
})

r e f E
export class PereComponent implements OnInit {

ch
@ViewChild(FilsComponent) fils: FilsComponent;

©A
tab: Array<string> = [’premier’, ’deuxième’, ’troisième’];
nord = ’Lille’;
sud = ’Marseille’;
capitale = ’Paris’;
constructor() { }

ngOnInit() { }
}

H & H: Research and Training 28 / 61


Décorateurs d’interaction Exemple avec @ViewChild()

Le décorateur @ViewChild() a un attribut static qui a par défaut la valeur false

import { Component, OnInit, ViewChild } from ’@angular/core’;


import { FilsComponent } from ’../fils/fils.component’;

@Component({
selector: ’app-pere’,
templateUrl: ’./pere.component.html’,

})
styleUrls: [’./pere.component.css’]

H I ©
export class PereComponent implements OnInit {
U EL
O
LM
@ViewChild(FilsComponent, { static: false }) fils: FilsComponent;

r e f E
tab: Array<string> = [’premier’, ’deuxième’, ’troisième’];
nord = ’Lille’;
ch
©A
sud = ’Marseille’;
capitale = ’Paris’;
constructor() { }

ngOnInit() { }
}

{ static: false } car les attributs du composant enfant sont alimentés par le père et ne
sont donc pas initialisés dans le composant.
H & H: Research and Training 29 / 61
Décorateurs d’interaction Exemple avec @ViewChild()

on ne peut accéder aux attributs d’un composant enfant non-statique qu’après initiation
de la vue

import { Component, OnInit, ViewChild } from ’@angular/core’;


import { FilsComponent } from ’../fils/fils.component’;

@Component({
selector: ’app-pere’,
templateUrl: ’./pere.component.html’,
styleUrls: [’./pere.component.css’]
H I ©
})
export class PereComponent implements OnInit {
U EL
O
f E LM
@ViewChild(FilsComponent, { static: false }) fils: FilsComponent;

nord = ’Lille’;
ch r e
tab: Array<string> = [’premier’, ’deuxième’, ’troisième’];

©A
sud = ’Marseille’;
capitale = ’Paris’;
constructor() { }

ngOnInit() {
console.log(this.fils.ordre);
}
}

ce code génère une erreur car le composant fils est encore indéfini.
H & H: Research and Training 30 / 61
Décorateurs d’interaction Exemple avec @ViewChild()

En mettant { static: true }, on indique qu’il ne faut plus attendre l’initiation de la vue
(fils) car ses données sont statiques
import { Component, OnInit, ViewChild } from ’@angular/core’;
import { FilsComponent } from ’../fils/fils.component’;

@Component({
selector: ’app-pere’,
templateUrl: ’./pere.component.html’,
styleUrls: [’./pere.component.css’]
H I ©
EL
})
export class PereComponent implements OnInit {
O U
f E LM
@ViewChild(FilsComponent, { static: true }) fils: FilsComponent;
tab: Array<string> = [’premier’, ’deuxième’, ’troisième’];
nord = ’Lille’;
ch r e
©A
sud = ’Marseille’;
capitale = ’Paris’;
constructor() { }
ngOnInit() {
console.log(this.fils.ordre); // affiche undefined
}
}

H & H: Research and Training 31 / 61


Décorateurs d’interaction Exemple avec @ViewChild()

En mettant { static: true }, on indique qu’il ne faut plus attendre l’initiation de la vue
(fils) car ses données sont statiques
import { Component, OnInit, ViewChild } from ’@angular/core’;
import { FilsComponent } from ’../fils/fils.component’;

@Component({
selector: ’app-pere’,
templateUrl: ’./pere.component.html’,
styleUrls: [’./pere.component.css’]
H I ©
EL
})
export class PereComponent implements OnInit {
O U
f E LM
@ViewChild(FilsComponent, { static: true }) fils: FilsComponent;
tab: Array<string> = [’premier’, ’deuxième’, ’troisième’];
nord = ’Lille’;
ch r e
©A
sud = ’Marseille’;
capitale = ’Paris’;
constructor() { }
ngOnInit() {
console.log(this.fils.ordre); // affiche undefined
}
}

Affecter une valeur à ordre dans fils.component.ts et vérifier que cette valeur est
affichée à la place de undefined.
H & H: Research and Training 31 / 61
Décorateurs d’interaction Exemple avec @ViewChild()

Remettons { static: false } et indiquons qu’il faut attendre que la vue soit initiée
pour accéder aux attributs
import { Component, OnInit, ViewChild, AfterViewInit } from ’@angular/
core’;
import { FilsComponent } from ’../fils/fils.component’;

@Component({
selector: ’app-pere’,
templateUrl: ’./pere.component.html’,
H I ©
EL
styleUrls: [’./pere.component.css’]
})
O
export class PereComponent implements OnInit, AfterViewInit { U
f E LM
@ViewChild(FilsComponent, { static: false }) fils: FilsComponent;

ch r e
tab: Array<string> = [’premier’, ’deuxième’, ’troisième’];

©A
nord = ’Lille’;
sud = ’Marseille’;
capitale = ’Paris’;
constructor() { }
ngOnInit() { }

ngAfterViewInit(): void {
console.log(this.fils.ordre); // affiche premier
}
}
H & H: Research and Training 32 / 61
Décorateurs d’interaction Exemple avec @ViewChildren()

Angular

Objectif

Récupérer les données de tous les composants fils à partir d’un


composant parent
H I ©
U EL
O
f E LM
ch r e
©A

H & H: Research and Training 33 / 61


Décorateurs d’interaction Exemple avec @ViewChildren()

Angular

Objectif

Récupérer les données de tous les composants fils à partir d’un


composant parent
H I ©
U EL
O
f E LM
Comment ?
ch r e
©A
Déclarer un QueryList (tableau) de composant fils comme
attribut d’un composant parent et le décorer avec
@ViewChildren()
Utiliser cet attribut pour récupérer les données souhaitées

H & H: Research and Training 33 / 61


Décorateurs d’interaction Exemple avec @ViewChildren()

Utilisons @ViewChildren pour récupérer un tableau de composant fils


import { Component, OnInit, AfterViewInit, ViewChildren, QueryList }
from ’@angular/core’;
import { FilsComponent } from ’../fils/fils.component’;

@Component({
selector: ’app-pere’,
templateUrl: ’./pere.component.html’,
styleUrls: [’./pere.component.css’]
H I ©
EL
})
export class PereComponent implements OnInit, AfterViewInit {
O U
undefined;
f E LM
@ViewChildren(FilsComponent) fils: QueryList<FilsComponent> |

ch r e
tab: Array<string> = [’premier’, ’deuxième’, ’troisième’];

©A
nord = ’Lille’;
sud = ’Marseille’;
capitale = ’Paris’;
constructor() { }
ngOnInit() { }

ngAfterViewInit(): void {
this.fils?.forEach(elt => console.log(elt));
// affiche les trois FilsComposant dans la console
}
}
H & H: Research and Training 34 / 61
Décorateurs d’interaction Exemple avec @ViewChildren()

Angular

Exercice 2 (suite de l’exercice list-item)

Depuis le composant list, on veut permettre à l’utilisateur de


I
modifier la couleur d’un ou tous les composant(s) item.
H ©
U
Pour cela, on ajoute deux nouvelles zones EdeLsaisie : une pour
l’indice du composant item (qu’on M O
souhaite modifier sa couleur)
f L
E qu’on veut lui attribuer.
et la deuxième est la couleur
r e
chpas (négatif ou supérieur ou égal au nombre
A
Si l’indice n’existe
© item), on modifie la couleur de tous les item.
des composants
Sinon, on modifie seulement la couleur du composant item ayant
cet indice.

H & H: Research and Training 35 / 61


Décorateurs d’interaction Exemple avec @ContentChild()

Angular

Objectif

Créer un composant titre pour l’utiliser chaque fois qu’on a un


composant père avec ses composants fils
H I ©
U EL
O
f E LM
ch r e
©A

H & H: Research and Training 36 / 61


Décorateurs d’interaction Exemple avec @ContentChild()

Angular

Objectif

Créer un composant titre pour l’utiliser chaque fois qu’on a un


composant père avec ses composants fils
H I ©
U EL
O
f E LM
Comment ?
ch r e
©A
Créer un composant titre.component
Utiliser la balise @ContentChild pour récupérer le contenu d’un
nœud enfant défini par la balise ng-content

H & H: Research and Training 36 / 61


Décorateurs d’interaction Exemple avec @ContentChild()

Angular
Le fichier titre.component.ts
import { Component, OnInit, Input } from ’@angular/core’;

@Component({
selector: ’app-titre’,
templateUrl: ’./titre.component.html’,
styleUrls: [’./titre.component.css’]
H I ©
})
export class TitreComponent implements OnInit {
U EL
O
LM
@Input() valeur: string;
@Input() couleur: string;
constructor() { }
r e f E
ch
©A
ngOnInit() {
}

Le fichier titre.component.html
<h1 [ngStyle]="{color: couleur}">{{ valeur }}</h1>

H & H: Research and Training 37 / 61


Décorateurs d’interaction Exemple avec @ContentChild()

Angular

Dans app.component.html, on ajoute la balise app-pere


contenant une balise app-titre
<app-pere>
H I ©
<app-titre [couleur]="’red’" [valeur]="’Mes
U EL
contacts’"></app-titre> O
</app-pere>
f E LM
ch r e
A
<router-outlet></router-outlet>
©

H & H: Research and Training 38 / 61


Décorateurs d’interaction Exemple avec @ContentChild()

Angular

Dans app.component.html, on ajoute la balise app-pere


contenant une balise app-titre
<app-pere>
H I ©
<app-titre [couleur]="’red’" [valeur]="’Mes
U EL
contacts’"></app-titre> O
</app-pere>
f E LM
ch r e
A
<router-outlet></router-outlet>
©
N’oublions pas les apostrophes autour de red et Mes contacts

H & H: Research and Training 38 / 61


Décorateurs d’interaction Exemple avec @ContentChild()

Angular

H I ©
Dans pere.component.html, on récupère sélectionne le titre dans la balise ng-content

<ng-content select="app-titre"></ng-content>
<ul>
U EL
O
LM
<app-fils [ordre]="tab[0]" [villeNaissance]="sud"></app-fils>

e E
<app-fils [ordre]="tab[1]" [villeNaissance]="nord"></app-fils>
f
<app-fils [ordre]="tab[2]" [villeNaissance]="capitale"></app-fils>
r
</ul>
ch
©A

H & H: Research and Training 39 / 61


Décorateurs d’interaction Exemple avec @ContentChild()

Dans pere.component.ts, on peut récupérer les attributs du composant titre


import { Component, OnInit, AfterContentInit, ViewChildren,
ContentChild } from ’@angular/core’;
import { TitreComponent } from ’../titre/titre.component’;

@Component({
selector: ’app-pere’,
templateUrl: ’./pere.component.html’,
styleUrls: [’./pere.component.css’]
H I ©
EL
})
export class PereComponent implements OnInit, AfterContentInit {
O U
TitreComponent;
f E LM
@ContentChild(TitreComponent, { static: false }) titre:

ch r e
tab: Array<string> = [’premier’, ’deuxième’, ’troisième’];

©A
nord = ’Lille’;
sud = ’Marseille’;
capitale = ’Paris’;
constructor() { }
ngOnInit() { }

ngAfterContentInit(): void {
console.log(this.titre.valeur);
}
}
H & H: Research and Training 40 / 61
Décorateurs d’interaction Exemple avec @ContentChildren()

Angular
Explication

@ContentChild permet de récupérer le premier composant


sélectionné par ng-content
@ContentChildren permet de récupérer tous les composants
H I ©
sélectionnés par ng-content
U EL
O
f E LM
ch r e
©A

H & H: Research and Training 41 / 61


Décorateurs d’interaction Exemple avec @ContentChildren()

Angular
Explication

@ContentChild permet de récupérer le premier composant


sélectionné par ng-content
@ContentChildren permet de récupérer tous les composants
H I ©
sélectionnés par ng-content
U EL
O
f E LM
ch r e
Comment ?
© A
Comme pour @ViewChildren(), déclarer un QueryList
(tableau) de composant et le décorer avec
@ContentChildren()
Utiliser cet attribut pour récupérer les données souhaitées

H & H: Research and Training 41 / 61


Décorateurs d’interaction Exemple avec @Output()

Angular
Avant de commencer

Créons deux composants parent et child

Définissions une route /parent pour le composant parent

H I ©
U EL
O
f E LM
ch r e
©A

H & H: Research and Training 42 / 61


Décorateurs d’interaction Exemple avec @Output()

Angular
Avant de commencer

Créons deux composants parent et child

Définissions une route /parent pour le composant parent

H I ©
EL
Dans cet exemple
M OU
Chaque élément child aura un
f E L texte pour saisir une note et un bouton
champ
e
chr composant parent
pour envoyer la valeur au

Le bouton©
A
sera désactivé après envoi

Le sélecteur du composant fils app-child sera ajouté dans


parent.component.html

Chaque fois que le composant parent reçoit une note d’un de ses fils, il
recalcule la moyenne et il l’affiche

H & H: Research and Training 42 / 61


Décorateurs d’interaction Exemple avec @Output()

Angular

Le fichier child.component.html
H I ©
<h6> {{ nom }} </h6>
U EL
<input type=number name=note [(ngModel)]=note>
O
<button (click)="send()" [disabled]="buttonStatus">
f E LM
Send
ch r e
©A
</button>

H & H: Research and Training 43 / 61


Décorateurs d’interaction Exemple avec @Output()

Angular
Le fichier child.component.ts
import { Component, OnInit, Input, Output, EventEmitter } from ’
@angular/core’;

@Component({
selector: ’app-child’,
templateUrl: ’./child.component.html’,
H I ©
EL
styleUrls: [’./child.component.css’]
})
O U
LM
export class ChildComponent implements OnInit {
@Input() nom = ’’;

e f E
@Output() message = new EventEmitter<number>();
r
ch
note = 0;

©A
buttonStatus = false;

constructor() { }

ngOnInit(): void { }
send(): void {
this.message.emit(this.note);
this.buttonStatus = true;
}
}
H & H: Research and Training 44 / 61
Décorateurs d’interaction Exemple avec @Output()

Angular
Le fichier parent.component.ts
import { Component, OnInit } from ’@angular/core’;

@Component({
selector: ’app-parent’,
templateUrl: ’./parent.component.html’,
styleUrls: [’./parent.component.css’]
H I ©
})
export class ParentComponent implements OnInit {
U EL
O
LM
moyenne = 0;
somme = 0;
nbr = 0;
r e f E
ch
enfants = [’Wick’, ’Hoffman’, ’Abruzzi’];

©A
constructor() { }
ngOnInit(): void { }
computeAvg(note: number): void {
this.somme += note;
this.nbr++;
this.moyenne = this.somme / this.nbr;
}
}

H & H: Research and Training 45 / 61


Décorateurs d’interaction Exemple avec @Output()

Angular

Le fichier parent.component.html
H I ©
U E L }} </h3>
<h3> Moyenne de mes enfants {{ moyenne
<app-child *ngFor="let enfant O
L M of enfants" [nom]="
f E
enfant" (message)="computeAvg($event)">
r e
</app-child>
A ch
©

H & H: Research and Training 46 / 61


Décorateurs d’interaction Exemple avec @Output()

Angular

Exercice
H I ©
Le composant parent doit permettre à l’utilisateur de saisir le
U EL
nom affecté à un composant child O
f E LM
ch r e
Modifiez les composants parent et child pour qu’on puisse
calculer la moyenne d’un nombre variable de notes
©A

H & H: Research and Training 47 / 61


Décorateurs d’interaction Exemple avec @Output()

Angular

Exercice clavier-touche

Considérons un composant clavier dont la classe associée a un attribut


lettres = [’a’, ’b’, ’c’, ’d’, ’e’, ’f’, ’g’, ’h’, ’i’,
’j’, ’k’, ’l’, ’m’, ’n’, ’o’, ’p’, ’q’, ’r’, ’s’, ’t’, ’u’,
’v’, ’w’, ’x’, ’y’, ’z’] .
H I ©
EL
Créez un composant fils nommé touche.
M OU
e f ELparent
Le composant touche a un attribut
lettres défini dans lercomposant
value recevant sa valeur du tableau

c h clavier.

Le nombre de A
© composants touche = taille du tableau lettres.
Chaque composant touche affiche la lettre qu’il a reçue sur un bouton.

En cliquant sur ce bouton, la lettre s’affiche (à la suite des autres) dans une
balise div définie dans le composant clavier.

H & H: Research and Training 48 / 61


Décorateurs d’interaction Exemple avec @Output()

Angular
Exercice panier-article

Créez deux composant panier et article

Définissez une route /panier pour le composant panier

H I ©
EL
Créez une interface avec les attributs id, désignation et prixUnitaire

O U
LM
Dans panier.component.ts, on considère le tableau articles donné dans
la slide suivante

r e f E
A ch
Dans panier.component.html, on affiche chaque élément de articles
dans un composant article
©
Chaque composant article contient un champ texte pour saisir une quantité
et un bouton qui permet d’envoyer l’article et la quantité au composant panier

Chaque fois qu’on clique sur le bouton ajouter d’un article, le composant
panier affiche le total

H & H: Research and Training 49 / 61


Décorateurs d’interaction Exemple avec @Output()

Angular

Contenu du tableau articles


articles: Array < Article > =[
H I ©
{ id: 1, description: ’clavier’, prixUnitaire: 20 },
U EL
O
LM
{ id: 2, description: ’souris’, prixUnitaire: 10 },

r e E
{ id: 3, description: ’écran’, prixUnitaire: 200 },
f
{ id: 4, description: ’modem’, prixUnitaire: 30 },
ch
©A
];

H & H: Research and Training 50 / 61


Variable locale et @ViewChild

Dans app.component.html, définissons un paragraphe ayant une variable locale ref


<p #ref>
contenu initial
</p>

Dans app.component.html, on peut récupérer ce paragraphe grâce à la variable locale


ref et appliquer des méthodes natives du JavaScript
import { Component,
I ©
ViewChild, ElementRef, AfterViewInit } from ’
H
EL
@angular/core’;

@Component({
O U
selector: ’app-root’,
templateUrl: ’./app.component.html’,
f E LM
ch
styleUrls: [’./app.component.css’]
r e
©A
})
export class AppComponent implements AfterViewInit {

@ViewChild(’ref’, {static: false}) p: ElementRef;

ngAfterViewInit(): void {
this.p.nativeElement.innerHTML += ’texte ajouté depuis le composant
.ts’;
}
}
H & H: Research and Training 51 / 61
Variable locale et @ViewChild

Angular

Exercice moyenne-note

Créons deux composants moyenne et note

Dans le composant moyenne, on peut ajouter plusieurs composants note (en cliquant sur
un bouton ajouter)
H I ©
EL
Le composant note permet à l’utilisateur de saisir une valeur et un coefficient. Pendant la
U
O
saisie, la valeur de la moyenne (définie dans le composant moyenne) se met à jour.

E LM
Vous pouvez utiliser une interface Note avec deux attributs valeur et coefficient
f
ch r e
©A

H & H: Research and Training 52 / 61


Variable locale et @ViewChild

Angular

Exercice moyenne-note

Créons deux composants moyenne et note

Dans le composant moyenne, on peut ajouter plusieurs composants note (en cliquant sur
un bouton ajouter)
H I ©
EL
Le composant note permet à l’utilisateur de saisir une valeur et un coefficient. Pendant la
U
O
saisie, la valeur de la moyenne (définie dans le composant moyenne) se met à jour.

E LM
Vous pouvez utiliser une interface Note avec deux attributs valeur et coefficient
f
ch r e
©A
Exercice (suite de l’exercice précédent)

Le composant note contenant la valeur min sera affiché en rouge et le composant contenant la
valeur max sera affiché en vert.

H & H: Research and Training 52 / 61


Service, subject et interaction

Angular
Avant de commencer
Créons trois composants container, first et second
Créons un service message

H I ©
EL
Ajoutons les deux sélecteurs app-first et app-second dans
container.component.html
M OU
E L pour le composant
Définissons une route /container
f
container
chr e
© A

H & H: Research and Training 53 / 61


Service, subject et interaction

Angular
Avant de commencer
Créons trois composants container, first et second
Créons un service message

H I ©
EL
Ajoutons les deux sélecteurs app-first et app-second dans
container.component.html
M OU
E L pour le composant
Définissons une route /container
f
container
chr e
© A
Contenu de app.component.html
<app-first></app-first>
<app-second></app-second>

H & H: Research and Training 53 / 61


Service, subject et interaction

Angular

Idée
Définir un subject dans message.service.ts H I ©
UEL
O
Injecter le service dans le constructeur de deux composants
first et second
f E LM
r e
chpour émettre les données d’un composant vers
Utiliser le service
un autre© A

H & H: Research and Training 54 / 61


Service, subject et interaction

Angular
Contenu de notre service
import { Injectable } from ’@angular/core’;
import { Subject } from ’rxjs’;

@Injectable({
providedIn: ’root’
H I ©
})
UEL
export class MessageService { O
private subject = new Subject<string>();
f E LM
constructor() { }
ch r e
©A
envoyerMessage(msg: string) {
this.subject.next(msg);
}
accederMessage() {
return this.subject;
}
}
H & H: Research and Training 55 / 61
Service, subject et interaction

Angular

Le fichier first.component.html
H I ©
<div>
UEL
Message : <input type=text [(ngModel)]="msg" >
O
<button (click)="ajouterMessage()">Ajouter message
f E LM
</button>
ch r e
©A
</div>

H & H: Research and Training 56 / 61


Service, subject et interaction

Angular
Définissons ajouterMessage() dans first.component.ts et utilisons
MessageService pour envoyer le message aux observateurs
import { Component, OnInit } from ’@angular/core’;
import { MessageService } from ’../services/message.service’;

@Component({
selector: ’app-first’,
H I ©
templateUrl: ’./first.component.html’,
styleUrls: [’./first.component.css’]
UEL
O
LM
})
export class FirstComponent implements OnInit {

r e f E
msg: string;
ch
©A
constructor(private messageService: MessageService) { }
ngOnInit() { }

ajouterMessage() {
this.messageService.envoyerMessage(this.msg);
this.msg = ’’;
}
}

H & H: Research and Training 57 / 61


Service, subject et interaction

Angular

Dans second.component.html, on affiche la liste de messages


envoyés par FirstComponent
H I ©
<ul>
UEL
O
<li *ngFor="let message of messages">
{{ message }}
f E LM
</li>
ch r e
</ul>
©A

H & H: Research and Training 58 / 61


Service, subject et interaction

Dans second.component.ts , il faut s’abonner au subject et utiliser la méthode


accederMessage() pour récupérer les messages envoyés
import { Component, OnInit, OnDestroy } from ’@angular/core’;
import { MessageService } from ’../services/message.service’;
import { Subscription } from ’rxjs’;

@Component({
selector: ’app-second’,
templateUrl: ’./second.component.html’,
H I ©
EL
styleUrls: [’./second.component.css’]
})
export class SecondComponent implements OnInit, OnDestroy {
O U
messages = [];
f E LM
subscription: Subscription;
ch r e
©A
constructor(private messageService: MessageService) { }
ngOnInit() {
this.subscription = this.messageService.accederMessage().subscribe(
msg => this.messages.push(msg)
);
}
ngOnDestroy() {
this.subscription.unsubscribe();
}
}
H & H: Research and Training 59 / 61
Service, subject et interaction

Angular

Exercice
H I ©
EL
OU
On veut que l’échange entre deux composants soit bidirectionnel.
M
le L
Quand le premier envoie,E
r e f deuxième affiche et inversement.

A ch
©

H & H: Research and Training 60 / 61


Service, subject et interaction

Angular
Exercice
Créez deux composant tchat et participant
Définissez une route /tchat pour le composant tchat
H I ©
Le composant tchat contient un champ texte nom et un bouton
UEL
ajouter qui permet d’ajouter un nouveau composant
O
participant dans tchat
f E LM
ch r e
Chaque composant participant peut envoyer des messages à
©A
tous les autres participants
Les participants reçoivent immédiatement les messages envoyés
et les affichent
Un participant n’affiche pas ses propres messages

H & H: Research and Training 61 / 61

Vous aimerez peut-être aussi