I want to manually subscribe to an event emitted by a directive, which, by design, should be available to multiple components of my application. At the moment the structure looks like this:
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 looks like this:
@NgModule({
imports: [ BrowserModule, HttpModule, JsonpModule, RouterModule.forRoot(appRoutes) ],
declarations: [ AppComponent, FooComponent, BarComponent, ParentComponent, DraggableDirective ],
bootstrap: [ AppComponent ]
})
Later in the development, another Parent component will be listening to draggable directive and implement its own logic.
None of the children component knows (or should care) about Draggable Directive doing anything to it. The parent component should. So, in parent component:
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();
}
And here is the directive, using Subject and not EventEmitter, as recommended elsewhere:
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);
}
}
}
I get console logging "emitting" with the correct values. I never get "listening" from the parent component in the console. What am I doing wrong here?