Angular 2:直接父组件不监听子组件发出的事件

时间:2017-02-20 00:09:25

标签: angular event-handling

我有一个基本的角应用程序,有3个组件,如下所示:

  1. car-component ,这是主要或父组件。
  2. carousel-component (汽车零部件的孩子,*使用ng-content)
  3. 儿童成分(轮播组件的孩子)
  4. 子组件内的按钮在单击时使用EventEmitter()发出事件。从plunker中的代码可以看出,汽车组件(主要组件或主组件)能够监听并捕获其子组件发出的事件(即 child-component.ts )和{{text}}在汽车零部件模板中更新。

    然而,作为子组件的直接父级的 carousel-component 无法捕获相同的事件,并且在carousel-component内没有更新文本。

    轿厢component.ts

    import  {Component} from 'angular2/core';
    import {CarouselComponent} from './carousel-component';
    import {Child} from './child.component';
    
    @Component({
        selector: 'my-app',
        template: `
                  <div style="border:1px solid #CCC; padding: 5px; margin: 5px;">
                    car-comp txt: {{text}}
                    <carousel-component>
                        <child (changed)="onChange($event)"></child>
                    </carousel-component>
                  </div>
        `,
        directives : [Child, CarouselComponent]
    })
    export class CarComponent {
    
        text: string = '?';
    
        onChange(value) {
            console.log('car-component onChange fn..');
           this.text = value;
        }
    
    }
    

    转盘-component.ts

    import  {Component, EventEmitter} from 'angular2/core';
    import {Output} from 'angular2/core';
    
    @Component({
        selector: 'carousel-component',
        template: `
                    <div style="background: #CCC; padding: 10px;">
                    <div>carousel-component txt: {{carouselTxt}}</div>
                    <ng-content></ng-content>
                    </div>
                 `,
    })
    export class CarouselComponent {
    
        carouselTxt: string = '?';
    
        changed = new EventEmitter();
    
        onChange(value) {
            console.log('carousel-comp onChange called..');
            this.carouselTxt = value;
        }
    
    }
    

    child.component.ts

    import  {Component, EventEmitter} from 'angular2/core';
    import {Output} from 'angular2/core';
    
    @Component({
        selector: 'child',
        template: `
                    <div style="background: #FFF; padding: 10px;">
                    child-comp txt: 
                    <input type ="text" #textInput value="{{txt}}">
                    <button (click)="onChange(textInput.value)">Emit</button>
                    </div>
                 `,
        outputs:['changed']
    })
    export class Child {
    
        txt: string = 'abc';
    
        changed = new EventEmitter();
    
        onChange(value) {
            this.txt = value;
            this.changed.emit(value);
        }
    
    }
    

    有人可以让我知道我在哪里错了吗?

    https://plnkr.co/edit/h9mjlo?p=preview

3 个答案:

答案 0 :(得分:0)

在您的汽车组件中,您正在侦听孩子的事件已更改并将其绑定到onChange。由于这是在你的汽车零部件模板中,它只将它绑定到汽车组件的改变方法,而不是轮播组件。

要使子组件的更改事件对所有父级的父级都可见,请创建一个所有父级订阅的服务。有关如何执行此操作的指南,请访问:https://angular.io/docs/ts/latest/cookbook/component-communication.html#!#bidirectional-service

答案 1 :(得分:0)

正如@Ricardo的最后一个答案所提到的,car-component正在为子组件提供selctor。要在carousel-component中侦听事件,请从car-component模板中删除子组件,并将其添加到carousel-component模板中。并且您可以在旋转木马组件中再添加一个事件发射器,它将到达汽车组件的父级。那个事件可以通过onChange()

来解决

答案 2 :(得分:0)

在CarouselComponent中使用ContentChildren和ngAfterContentInit,无需添加服务&#39;或&#39;将模板移出汽车零部件模板。

export class CarouselComponent {

    carouselTxt: string = '?';

    @ContentChildren(Child) childItems:QueryList<Child> = new QueryList<Child>();

    ngAfterContentInit () {
      this.childItems.toArray().forEach((item, n)=>{
        item.changed.subscribe(
          (val)=> { this.carouselTxt = val; },
          (e)=> { console.log('e::', e); },
          (c)=>{ console.log('c::', c); }
        );
      });
    }

}

解决方案:https://plnkr.co/edit/x2mO0r?p=preview