Angular 2
Directivas y componentes: @Input @Output
Buscar..
Sintaxis
- Enlace unidireccional del componente principal al componente anidado: [propertyName]
- Enlace unidireccional de componente anidado a componente principal: (propertyName)
- Enlace bidireccional (también conocido como notación de caja de banana): [(propertyName)]
Ejemplo de entrada
@input es útil para enlazar datos entre componentes
Primero, importalo en tu componente
import { Input } from '@angular/core';
Luego, agregue la entrada como una propiedad de su clase de componente
@Input() car: any;
Digamos que el selector de su componente es 'auto-componente', cuando llama al componente, agregue el atributo 'automóvil'
<car-component [car]="car"></car-component>
Ahora se puede acceder a su automóvil como un atributo en su objeto (this.car)
Ejemplo completo:
- 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];
}
}
- garage.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 y @Output en un componente anidado
Una directiva de botón que acepta un @Input()
para especificar un límite de clic hasta que el botón se deshabilite. El componente principal puede escuchar un evento que se emitirá cuando se alcance el límite de clics a través de @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);
}
}
}
Componente principal que utiliza la directiva Button y alerta un mensaje cuando se alcanza el límite de clics:
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 con datos asíncronos
A veces es necesario obtener datos de forma asíncrona antes de pasarlos a un componente secundario para usarlos. Si el componente hijo intenta usar los datos antes de que se hayan recibido, generará un error. Puede usar ngOnChanges
para detectar cambios en @Input
s de un componente y esperar hasta que se definan antes de actuar sobre ellos.
Componente padre con llamada asíncrona a un punto final
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);
}
}
Componente hijo que tiene datos asíncronos como entrada.
Este componente hijo toma los datos asíncronos como entrada. Por lo tanto, debe esperar a que los datos existan antes de usarlos. Usamos ngOnChanges, que se activa cada vez que cambia la entrada de un componente, verificamos si existen los datos y los utilizamos si es así. Observe que la plantilla para el niño no se mostrará si una propiedad que se basa en los datos que se están pasando no es verdadera.
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;
}
}