Я хочу вручную подписаться на событие, выпущенное директивой, которая по дизайну должна быть доступна для нескольких компонентов моего приложения. На данный момент структура выглядит следующим образом:Angular2: rxjs Subject in Angular2 взаимодействие с родительским компонентом
AppComponent
Draggable.Directive (uses an attribute of a DOM element to control the behaviour)
(and then, via routing)
Parent1 Component
Child1 Component
Child2 Component
app.module выглядит следующим образом:
@NgModule({
imports: [ BrowserModule, HttpModule, JsonpModule, RouterModule.forRoot(appRoutes) ],
declarations: [ AppComponent, FooComponent, BarComponent, ParentComponent, DraggableDirective ],
bootstrap: [ AppComponent ]
})
Позже в развитии, другой компонент Родителя будет слушать перетаскиваемую директиву и реализовывать свои собственный логика.
Ни один из компонентов для детей не знает (или не должен заботиться) о директиве Draggable, что-либо делает с ней. Родительский компонент должен. Так, в родительском компоненте:
import { Component, OnInit, ViewChild } from '@angular/core';
import { DraggableDirective } from './draggable.directive';
import { FooComponent } from './foo.component';
import { BarComponent } from './bar.component';
@Component({
selector: 'parent-view',
templateUrl: './parent.component.html',
providers: [DraggableDirective],
moduleId: module.id
})
export class ParentComponent implements OnInit {
@ViewChild('foo') fooC:FooComponent;
@ViewChild('bar') barC:BarComponent;
constructor(private draggable:DraggableDirective){
draggable.droppedOn.subscribe(event => {
console.log('listening', event);
})
}
ngOnInit(): void {
// updated
// child view components
this.fooC.fooInit();
}
А вот директива, используя Subject и не EventEmitter, как это было рекомендовано в другом месте:
import { Directive, ElementRef, Renderer, HostListener, AfterViewInit } from '@angular/core';
import {Subject} from 'rxjs/Rx';
@Directive({
selector: '[draggable], [data-draggable]'
})
export class DraggableDirective implements AfterViewInit {
public droppedOn = new Subject();
//... at some point this method is envoked
couldDrop():void {
if (this.dElem) {
let _attr = this.dElem.dataset.indexed;
console.log('emitting', _attr);
this.droppedOn.next(_attr);
}
}
}
я получаю консольного протоколирование "излучающий" с правильным значения. Я никогда не получаю «прослушивание» от родительского компонента в консоли. Что я здесь делаю неправильно?
Хорошо, пока все хорошо. Должен ли я затем подписываться на Subject() на дочернем компоненте и перенаправлять его на родительский компонент? – pop
@pop Нет, вы используете аннотацию '@ ViewChildren' и' QueryList', которая сама наблюдает в родительском компоненте, чтобы получить обновленный список всех директив 'DraggableDirective'. Там вы можете получить доступ к свойству 'lostOn', в котором каждый из них подписал его. – martin
См. Http://stackoverflow.com/questions/32693061/angular-2-typescript-get-hold-of-an-element-in-the-template/35209681#35209681 – martin