Angular 2
Dyrektywy i komponenty: @Input @Output
Szukaj…
Składnia
- Powiązanie jednokierunkowe z komponentu nadrzędnego do komponentu zagnieżdżonego: [propertyName]
- Powiązanie jednokierunkowe z komponentu zagnieżdżonego do komponentu nadrzędnego: (propertyName)
- Wiązanie dwukierunkowe (inaczej notacja pola bananowego): [(propertyName)]
Przykład wprowadzania
@input jest przydatne do wiązania danych między komponentami
Najpierw zaimportuj go do swojego komponentu
import { Input } from '@angular/core';
Następnie dodaj dane wejściowe jako właściwość klasy komponentu
@Input() car: any;
Powiedzmy, że selektor twojego komponentu to „car-component”, kiedy wywołujesz komponent, dodaj atrybut „car”
<car-component [car]="car"></car-component>
Teraz twój samochód jest dostępny jako atrybut w twoim obiekcie (this.car)
Pełny przykład:
- car.entity.ts
export class CarEntity {
constructor(public brand : string, public color : string) {
}
}
- car.component.ts
import { Component, Input } from '@angular/core';
import {CarEntity} from "./car.entity";
@Component({
selector: 'car-component',
template: require('./templates/car.html'),
})
export class CarComponent {
@Input() car: CarEntity;
constructor() {
console.log('gros');
}
}
- garage.component.ts
import { Component } from '@angular/core';
import {CarEntity} from "./car.entity";
import {CarComponent} from "./car.component";
@Component({
selector: 'garage',
template: require('./templates/garage.html'),
directives: [CarComponent]
})
export class GarageComponent {
public cars : Array<CarEntity>;
constructor() {
var carOne : CarEntity = new CarEntity('renault', 'blue');
var carTwo : CarEntity = new CarEntity('fiat', 'green');
var carThree : CarEntity = new CarEntity('citroen', 'yellow');
this.cars = [carOne, carTwo, carThree];
}
}
- garaż.html
<div *ngFor="let car of cars">
<car-component [car]="car"></car-component>
</div>
- car.html
<div>
<span>{{ car.brand }}</span> |
<span>{{ car.color }}</span>
</div>
Angular2 @Input i @Output w zagnieżdżonym komponencie
Dyrektywa Button, która akceptuje @Input()
celu określenia limitu kliknięć do momentu wyłączenia przycisku. Komponent nadrzędny może nasłuchiwać zdarzenia, które zostanie wyemitowane po osiągnięciu limitu kliknięć za pośrednictwem @Output
:
import { Component, Input, Output, EventEmitter } from '@angular/core';
@Component({
selector: 'limited-button',
template: `<button (click)="onClick()"
[disabled]="disabled">
<ng-content></ng-content>
</button>`,
directives: []
})
export class LimitedButton {
@Input() clickLimit: number;
@Output() limitReached: EventEmitter<number> = new EventEmitter();
disabled: boolean = false;
private clickCount: number = 0;
onClick() {
this.clickCount++;
if (this.clickCount === this.clickLimit) {
this.disabled = true;
this.limitReached.emit(this.clickCount);
}
}
}
Komponent nadrzędny, który korzysta z dyrektywy Button i ostrzega komunikat, gdy limit kliknięć zostanie osiągnięty:
import { Component } from '@angular/core';
import { LimitedButton } from './limited-button.component';
@Component({
selector: 'my-parent-component',
template: `<limited-button [clickLimit]="2"
(limitReached)="onLimitReached($event)">
You can only click me twice
</limited-button>`,
directives: [LimitedButton]
})
export class MyParentComponent {
onLimitReached(clickCount: number) {
alert('Button disabled after ' + clickCount + ' clicks.');
}
}
Angular2 @Input z danymi asynchronicznymi
Czasami trzeba asynchronicznie pobierać dane przed przekazaniem ich do komponentu potomnego w celu użycia. Jeśli komponent potomny spróbuje użyć danych przed ich otrzymaniem, zgłosi błąd. Możesz użyć ngOnChanges
do wykrycia zmian w @Input
komponentów i poczekaj, aż zostaną zdefiniowane, zanim zaczniesz działać na ich podstawie.
Składnik nadrzędny z wywołaniem asynchronicznym do punktu końcowego
import { Component, OnChanges, OnInit } from '@angular/core';
import { Http, Response } from '@angular/http';
import { ChildComponent } from './child.component';
@Component ({
selector : 'parent-component',
template : `
<child-component [data]="asyncData"></child-component>
`
})
export class ParentComponent {
asyncData : any;
constructor(
private _http : Http
){}
ngOnInit () {
this._http.get('some.url')
.map(this.extractData)
.subscribe(this.handleData)
.catch(this.handleError);
}
extractData (res:Response) {
let body = res.json();
return body.data || { };
}
handleData (data:any) {
this.asyncData = data;
}
handleError (error:any) {
console.error(error);
}
}
Komponent potomny, który ma dane asynchroniczne jako dane wejściowe
Ten komponent potomny przyjmuje dane asynchroniczne jako dane wejściowe. Dlatego musi zaczekać na istnienie danych przed ich użyciem. Używamy ngOnChanges, który jest uruchamiany przy każdej zmianie danych wejściowych komponentu, sprawdzamy, czy dane istnieją i używamy ich, jeśli tak się dzieje. Zauważ, że szablon dla dziecka nie będzie wyświetlany, jeśli właściwość, która opiera się na przekazywanych danych, nie jest prawdziwa.
import { Component, OnChanges, Input } from '@angular/core';
@Component ({
selector : 'child-component',
template : `
<p *ngIf="doesDataExist">Hello child</p>
`
})
export class ChildComponent {
doesDataExist: boolean = false;
@Input('data') data : any;
// Runs whenever component @Inputs change
ngOnChanges () {
// Check if the data exists before using it
if (this.data) {
this.useData(data);
{
}
// contrived example to assign data to reliesOnData
useData (data) {
this.doesDataExist = true;
}
}