2016-12-06 65 views
1

我想手動訂閱由指令發出的事件,該指令在設計上應該可用於我的應用程序的多個組件。目前的結構是這樣的:Angular2:rxjs主題在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(); 
    } 

這裏是指令,使用主題和不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); 

     } 

    } 
} 

我得到了控制檯日誌「發光」用正確的值。我從來沒有從控制檯中的父組件「收聽」。我在這裏做錯了什麼?

回答

2

您創建的指令不是服務,因此它不會轉到@Componentproviders數組,而是使用declarations代替。例如見https://angular.io/docs/ts/latest/guide/attribute-directives.html(你可以將其添加到NgModule爲好)

ParentComponent不能得到你的模板,以它的構造函數的地方使用的指令的一個實例。這就是ViewChildren的用途。例如,請參閱:https://angular.io/docs/ts/latest/api/core/index/QueryList-class.html

因此,在ParentComponent中,您訂閱了不同於您的模板正在使用的DraggableDirective實例。

+0

好吧,迄今爲止這麼好。我是否應該在子組件上訂閱Subject()並將其轉發給父組件? – pop

+0

@pop不,你使用'@ ViewChildren'註解和'QueryList',它是父組件中的Observable本身,以獲得所有'DraggableDirective'指令的更新列表。在那裏你可以訪問每個訂閱它的'droppedOn'屬性。 – martin

+0

請參閱http://stackoverflow.com/questions/32693061/angular-2-typescript-get-hold-of-an-element-in-the-template/35209681#35209681 – martin