Angular 2
Interactions entre composants
Recherche…
Syntaxe
-
<element [variableName]="value"></element> //Declaring input to child when using @Input() method.
-
<element (childOutput)="parentFunction($event)"></element> //Declaring output from child when using @Output() method.
-
@Output() pageNumberClicked = new EventEmitter(); //Used for sending output data from child component when using @Output() method.
-
this.pageNumberClicked.emit(pageNum); //Used to trigger data output from child component. when using @Output() method.
-
@ViewChild(ComponentClass) //Property decorator is required when using ViewChild.
Paramètres
prénom | Valeur |
---|---|
nombre de pages | Utilisé pour indiquer le nombre de pages à créer pour le composant enfant. |
pageNumberClicked | Nom de la variable de sortie dans le composant enfant. |
pageChanged | Fonction du composant parent qui écoute les sorties des composants enfants. |
Parent - Interaction enfant utilisant les propriétés @Input & @Output
Nous avons un DataListComponent qui affiche des données que nous tirons d'un service. DataListComponent a également un composant PagerComponent en tant qu'enfant.
PagerComponent crée une liste de numéros de page en fonction du nombre total de pages qu'il reçoit du DataListComponent. PagerComponent permet également à DataListComponent de savoir quand l'utilisateur clique sur un numéro de page via la propriété Output.
import { Component, NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { DataListService } from './dataList.service';
import { PagerComponent } from './pager.component';
@Component({
selector: 'datalist',
template: `
<table>
<tr *ngFor="let person of personsData">
<td>{{person.name}}</td>
<td>{{person.surname}}</td>
</tr>
</table>
<pager [pageCount]="pageCount" (pageNumberClicked)="pageChanged($event)"></pager>
`
})
export class DataListComponent {
private personsData = null;
private pageCount: number;
constructor(private dataListService: DataListService) {
var response = this.dataListService.getData(1); //Request first page from the service
this.personsData = response.persons;
this.pageCount = response.totalCount / 10;//We will show 10 records per page.
}
pageChanged(pageNumber: number){
var response = this.dataListService.getData(pageNumber); //Request data from the service with new page number
this.personsData = response.persons;
}
}
@NgModule({
imports: [CommonModule],
exports: [],
declarations: [DataListComponent, PagerComponent],
providers: [DataListService],
})
export class DataListModule { }
PagerComponent répertorie tous les numéros de page. Nous définissons l'événement click sur chacun d'eux afin que nous puissions informer le parent du numéro de page cliqué.
import { Component, Input, Output, EventEmitter } from '@angular/core';
@Component({
selector: 'pager',
template: `
<div id="pager-wrapper">
<span *ngFor="#page of pageCount" (click)="pageClicked(page)">{{page}}</span>
</div>
`
})
export class PagerComponent {
@Input() pageCount: number;
@Output() pageNumberClicked = new EventEmitter();
constructor() { }
pageClicked(pageNum){
this.pageNumberClicked.emit(pageNum); //Send clicked page number as output
}
}
Parent - Interaction enfant avec ViewChild
Viewchild offre une interaction à sens unique entre parent et enfant. Il n'y a pas de retour ou de sortie de l'enfant lorsque ViewChild est utilisé.
Nous avons un DataListComponent qui affiche des informations. DataListComponent a PagerComponent comme étant son enfant. Lorsque l'utilisateur effectue une recherche sur DataListComponent, il obtient des données d'un service et demande à PagerComponent d'actualiser la disposition de la pagination en fonction du nouveau nombre de pages.
import { Component, NgModule, ViewChild } from '@angular/core';
import { CommonModule } from '@angular/common';
import { DataListService } from './dataList.service';
import { PagerComponent } from './pager.component';
@Component({
selector: 'datalist',
template: `<input type='text' [(ngModel)]="searchText" />
<button (click)="getData()">Search</button>
<table>
<tr *ngFor="let person of personsData">
<td>{{person.name}}</td>
<td>{{person.surname}}</td>
</tr>
</table>
<pager></pager>
`
})
export class DataListComponent {
private personsData = null;
private searchText: string;
@ViewChild(PagerComponent)
private pagerComponent: PagerComponent;
constructor(private dataListService: DataListService) {}
getData(){
var response = this.dataListService.getData(this.searchText);
this.personsData = response.data;
this.pagerComponent.setPaging(this.personsData / 10); //Show 10 records per page
}
}
@NgModule({
imports: [CommonModule],
exports: [],
declarations: [DataListComponent, PagerComponent],
providers: [DataListService],
})
export class DataListModule { }
De cette manière, vous pouvez appeler des fonctions définies sur des composants enfants.
Le composant enfant n'est pas disponible tant que le composant parent n'est pas rendu. Tenter d'accéder à l'enfant avant les parents Le AfterViewInit
vie du crochet AfterViewInit
provoquera des exceptions.
Interaction bidirectionnelle parent-enfant via un service
Service utilisé pour la communication:
import { Injectable } from '@angular/core';
import { Subject } from 'rxjs/Subject';
@Injectable()
export class ComponentCommunicationService {
private componentChangeSource = new Subject();
private newDateCreationSource = new Subject<Date>();
componentChanged$ = this.componentChangeSource.asObservable();
dateCreated$ = this.newDateCreationSource.asObservable();
refresh() {
this.componentChangeSource.next();
}
broadcastDate(date: Date) {
this.newDateCreationSource.next(date);
}
}
Composant parent:
import { Component, Inject } from '@angular/core';
import { ComponentCommunicationService } from './component-refresh.service';
@Component({
selector: 'parent',
template: `
<button (click)="refreshSubsribed()">Refresh</button>
<h1>Last date from child received: {{lastDate}}</h1>
<child-component></child-component>
`
})
export class ParentComponent implements OnInit {
lastDate: Date;
constructor(private communicationService: ComponentCommunicationService) { }
ngOnInit() {
this.communicationService.dateCreated$.subscribe(newDate => {
this.lastDate = newDate;
});
}
refreshSubsribed() {
this.communicationService.refresh();
}
}
Composant enfant:
import { Component, OnInit, Inject } from '@angular/core';
import { ComponentCommunicationService } from './component-refresh.service';
@Component({
selector: 'child-component',
template: `
<h1>Last refresh from parent: {{lastRefreshed}}</h1>
<button (click)="sendNewDate()">Send new date</button>
`
})
export class ChildComponent implements OnInit {
lastRefreshed: Date;
constructor(private communicationService: ComponentCommunicationService) { }
ngOnInit() {
this.communicationService.componentChanged$.subscribe(event => {
this.onRefresh();
});
}
sendNewDate() {
this.communicationService.broadcastDate(new Date());
}
onRefresh() {
this.lastRefreshed = new Date();
}
}
AppModule:
@NgModule({
declarations: [
ParentComponent,
ChildComponent
],
providers: [ComponentCommunicationService],
bootstrap: [AppComponent] // not included in the example
})
export class AppModule {}