Wyszukaj / o blogu

Angular: przekazywanie danych pomiędzy kompenentami (input, output, eventEmitter, ViewChild)

Opublikowano śro 23 grudnia 2020 w angular • 2 min read


angular

@Input oraz @Output

1) przekazanie danych 'w dół' (od rodzica do dziecka)

@Input - Dekoratory pozwalające na rozbicie logiki aplikacji na mniejsze części/komponenty i komunikowanie się danymi pomiędzy nimi. Dekorator @Input można porównać do właściwość (property/props) komponentu w React tzn. pozwala na przekazanie do komponentu danych np.

// rodzic
<app-user [name]="Mike"></app-user>

gdzie komponent app-user przy pomocy dekoratora @Input ma zdefiniować właściwość name.

@Input() name: string;

2) przekazanie danych 'w górę' (od dziecka do rodzica)

@Output - pozwala na przekazanie informacji DO rodzica, aby tego dokoną należy stworzyć nową instancję klasy EventEmmiter (poprzez wywołanie funkcji konstruktora). 1) W klasie dziecka przy pomocy dekoratora @Output rejestrujemy EventEmmiter, który będzie przekazywał dane do rodzica - jego zmiana wywołana jest poprzez dedykowaną metodę klasy/komponentu dziecka.

@Output() nameChanged = new EventEmmiter<string>(); // typ generyczny odpowiadający typowi przesyłanych danych

onUserInput(event){
  this.nameChanged.emit(event.target.value);
}

// rodzic:
//html
<app-user (nameChanged)="onNameChanged($event)"></app-user>

// ts
[...]
// wartość która ulegnie zmianie
name = "Mike"

onNameChanged(newName) {
  this.name = newName;
}

Przykładowa aplikacja wykorzystująca tzw. Event Binding i wyżej wymienione dekoratory w sposób bezpośredni star-wars-angular-service-app (etap prze implementacą serwisu)

@ViewChild

Zapisanie w zmiennej referencji do dziecka danego elementu (dowolny jego element html jak i cały komponent). Pozwala na odwołanie się do publicznych pól dziecka przez rodzica. Rodzic decyduje z jakich pól dziecka będzie potrzebował.

Zadeklarowanie przy pomocy dekoratora - @ViewChild w klasie rodzica może wyglądać następująco:

"[...] Chcąc obserwować konkretny komponent deklarujesz typ zmiennej zgodny z klasą tego komponentu. Dzięki temu masz dostęp do publicznych pól i metod tej klasy. Odtąd, w dowolnym momencie możesz używać this.child jak zwykłego pola klasy rodzica."

@ViewChild(ChildComponent) child: ChildComponent;

"W przypadku tagów HTML musisz oznaczyć ten tag poprzez dowolny string z przedrostkiem ‚#’. Potem tu używasz tego stringa jako identyfikator, na podstawie którego angular namierzy tag i przypisze do zmiennej. Inny jest też deklarowany typ – ElementRef, czyli referencja lokalna na konkretny element HTML [...]"

Lub w przypadku html

@ViewChild('ref') child: ElementRef;

Gdzie element html wygląda następującego

<div #ref></div>

Uwaga końcowa:

"Propercja klasy dziecka rodzica na początku jest undefined. Możesz odwoływać się do niej, dopiero po zainicjalizowaniu widoku i wystąpieniu zdarzenia ngAfterViewInit()."

Cytowane fragmenty tekstu za: @ViewChild(). Komunikacja komponentów]

Sięgnięcie do listy dzieci jest możliwe przy pomocy QueryList

@ViewChildren(ChildComponent) children: QueryList<ChildComponent>;

Źródła:

viewchild-komunikacja-komponentow