Ricerca…


Sintassi

  • <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.

Parametri

Nome Valore
pageCount Utilizzato per indicare il numero di pagine da creare nel componente figlio.
pageNumberClicked Nome della variabile di output nel componente figlio.
pageChanged Funzione al componente padre che ascolta i componenti figlio in uscita.

Interazione padre-figlio con proprietà @Input e @Output

Abbiamo un componente DataList che mostra i dati estratti da un servizio. DataListComponent ha anche un PagerComponent dato che è figlio.

PagerComponent crea l'elenco dei numeri di pagina in base al numero totale di pagine ricevute da DataListComponent. PagerComponent consente inoltre a DataListComponent di sapere quando l'utente fa clic su qualsiasi numero di pagina tramite la proprietà 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 elenca tutti i numeri di pagina. Impostiamo l'evento click su ognuno di essi in modo che possiamo far sapere al genitore il numero di pagina cliccato.

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 - Interazione bambino usando ViewChild

Viewchild offre un'interazione unidirezionale da genitore a figlio. Non vi è alcun feedback o output da parte del bambino quando viene utilizzato ViewChild.

Abbiamo un componente DataList che mostra alcune informazioni. DataListComponent ha PagerComponent come figlio. Quando l'utente effettua una ricerca su DataListComponent, ottiene un dato da un servizio e chiede a PagerComponent di aggiornare il layout di paging in base al nuovo numero di pagine.

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 { }

In questo modo è possibile chiamare le funzioni definite sui componenti figlio.

Il componente figlio non è disponibile fino al rendering del componente principale. Si tenta di accedere al bambino prima che i genitori AfterViewInit gancio cyle vita causerà un'eccezione.

Interazione genitore-figlio bidirezionale attraverso un servizio

Servizio utilizzato per la comunicazione:

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);
    }
}

Componente genitore:

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();
    }
}

Componente figlio:

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 {}


Modified text is an extract of the original Stack Overflow Documentation
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow