2016-06-07 45 views
34

在角度文档中,有一个关于倾听父母的孩子事件的话题。没关系。但我的目的是颠倒的!在我的应用程序中有一个包含管理页面布局视图(侧边栏菜单,任务栏,状态等)的'admin.component'。 在此父组件中,我配置了用于更改管理员其他页面之间的主视图的路由器系统。 问题在于改变后保存东西,用户点击任务栏中的保存按钮(放置在admin.component中),并且子组件必须监听该点击事件才能完成保存工作。孩子在Angular 2中倾听父母事件

+2

听起来像这样做的最佳做法是使用服务和可观察的派发事件。 – zpul

+0

你的问题是不是这个太不相似:http://stackoverflow.com/questions/35560860/in-angular2-how-to-let-child-components-communicate-with-each-other – freethebees

+0

@freethebees也许解决方案是一样的,但问题的形式是不同的,我的意图是找到解决这种情况的最佳方法。 –

回答

52

我觉得这个医生可以对你有所帮助:

事实上,你可以利用可观察的/受父提供给它的孩子。类似的东西:

@Component({ 
    (...) 
    template: ` 
    <child [parentSubject]="parentSubject"></child> 
    `, 
    directives: [ ChildComponent ] 
}) 
export class ParentComponent { 
    parentSubject:Subject<any> = new Subject(); 

    notifyChildren() { 
    this.parentSubject.next('some value'); 
    } 
} 

子组件可以对这个问题简单地订阅:

@Component({ 
    (...) 
}) 
export class ChildComponent { 
    @Input() 
    parentSubject:Subject<any>; 

    ngOnInit() { 
    this.parentSubject.subscribe(event => { 
     // called when the notifyChildren method is 
     // called in the parent component 
    }); 
    } 

    ngOnDestroy() { 
    // needed if child gets re-created (eg on some model changes) 
    // note that subsequent subscriptions on the same subject will fail 
    // so the parent has to re-create parentSubject on changes 
    this.parentSubject.unsubscribe(); 
    } 

} 

否则,你可以利用包含以类似的方式这样一个题目共享服务...

+0

除非父组件在ngInit中广播下一个值,否则我的子组件中的回调将不会运行。为什么会这样? – cjsimon

+2

在ViewChild上使用这种方法有什么优势吗? – sunnyiitkgp

+0

虽然看起来更专业,但在给我几个小时的时间来尝试一下我的情况后,在添加/删除子元素(因此取消订阅主题)时,我无法摆脱UnsubscribeErrors的麻烦。所以通过TimeBoxing的手段,我去了@StephenPaul更直接的答案。无论如何,感谢你的答案,可能我现在只是没有足够好的rxjs库来充分理解它,并对你的示例做出正确的(额外的)调整,使其工作完美无瑕。 –

52

为了后人的缘故,我想我会提到更传统的解决方案:只需获取对ViewChild的引用并直接调用该方法。

@Component({ 
    selector: 'app-child' 
}) 
export class ChildComponent { 

    notifyMe() { 
    console.log('Event Fired'); 
    } 
} 

@Component({ 
    selector: 'app-parent', 
    template: `<app-child #child></app-child>` 
}) 
export class ParentComponent { 

    @ViewChild('child') 
    private child: ChildComponent; 

    ngOnInit() { 
    this.child.notifyMe(); 
    } 
} 
+27

我从你的答案中学到了2件事 - 如何获得对孩子组件的引用,以及单词*后代的含义* –

+1

只要我进入父组件,它就会崩溃......'不能读取属性'notifyMe' undefined'。 –

+0

嗯,显然你的孩子组件不是由Angular设置的。确保ChildComponent具有正确的选择器。 –

1

如果我正确地理解了这个问题,在这里可能会有更多的裸骨法。假设 -

  • OP有一个父组件保存按钮
  • 需要保存的数据是在子组件
  • 所有其他数据的子组件可能需要可以由服务访问

在父组件

<button type="button" (click)="prop1=!prop1">Save Button</button> 
<app-child-component [setProp]='prop1'></app-child-component> 

而且在孩子..

prop1:boolean; 
    @Input() 
    set setProp(p: boolean) { 
    // -- perform save function here 
} 

这只是将按钮点击发送到子组件。从那里,子组件可以独立保存数据。

编辑:如果来自父模板的数据也需要与按钮单击一起传递,那么也可以使用此方法。让我知道如果是这样,我会更新代码示例。