typescript - Barnkomponenthendelser sendes til forelder
Jeg ønsker å implementere det vanlige Angular 1.x-mønsteret med å ha barndirektiver innenfor et foreldredirektiv i Angular 2. Her er min ønskede struktur.
<foo>
<bar>A</bar>
<bar>B</bar>
<bar>C</bar>
</foo>
Jeg ønsker at disse Bar-komponentene skal ha click-hendelser som blir sendt videre til Foo-komponenten.
Her er min Foo så langt:
@Component({
selector: 'foo',
template: `
<div>
<ng-content></ng-content>
</div>
`
})
export class Foo {
@ContentChildren(Bar) items: QueryList<Bar>;
}
Og her er min Bar:
@Component({
selector: 'Bar',
template: `
<div (click)="clickity()">
<ng-content></ng-content>
</div>
`
})
export class Bar {
clickity() {
console.log('Broadcast this to the parent please!');
}
}
Hvordan går jeg frem for å varsle Foo hver gang en av dens Bars blir klikket?
Svar #1
Du kan bruke en tjeneste for å sende data mellom komponenter hvis du ikke kan gjøre det ved å bruke @Output() dekoratøren. Her er et eksempel:
import {EventEmitter} from 'angular2/core';
export class EmitterService {
private static _emitters: { [channel: string]: EventEmitter<any> } = {};
static get(channel: string): EventEmitter<any> {
if (!this._emitters[channel])
this._emitters[channel] = new EventEmitter();
return this._emitters[channel];
}
}
Du importerer det der du trenger å sende ut eller abonnere på en hendelse:
// foo.component.ts
import {EmitterService} from '../path/to/emitter.service'
class Foo {
EmitterService.get("some_id").subscribe(data => console.log("some_id channel: ", data));
EmitterService.get("other_id").subscribe(data => console.log("other_id channel: ", data));
}
// bar.component.ts
import {EmitterService} from '../path/to/emitter.service'
class Bar {
onClick() {
EmitterService.get("some_id").emit('you clicked!');
}
onScroll() {
EmitterService.get("other_id").emit('you scrolled!');
}
}
et annet eksempel: plunker
Svar #2
Hvorfor ikke bruke @ContentChildren?
i bar.component.ts eksponerer vi clicked-hendelsen
@Output() clicked = new EventEmitter<BarComponent>();
onClick(){
this.clicked.emit(this);
}
i foo.component.ts abonnerer vi på click-hendelsen for hver
@ContentChildren(BarComponent) accordionComponents: QueryList<BarComponent>;
ngAfterViewInit() {
this.accordionComponents.forEach((barComponent: BarComponent) => {
barComponent.clicked.subscribe((bar: BarComponent) => doActionsOnBar(bar));
});
}
