2016-12-06 103 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