我是angular2的新手
<parent>
<router outlet><router outlet>
</parent>
我在父组件中有一个按钮,如果我单击该按钮,它应该调用子组件中的方法(在路由器插座中加载。)
有没有办法从父级调用子组件(在路由器插座中)方法。
答案 0 :(得分:8)
基本上有两种显示组件模板的方法:作为嵌套组件或路由目标。
嵌套组件
如果使用嵌套组件,则组件被视为具有“父组件/子组件”关系。
父组件的Html将如下所示:
<div>
<child></child>
</div>
其中“child”是子组件的选择器。然后,您可以使用@Input和@Output属性在两者之间进行通信。
如果您有嵌套组件时有关此技术的详细信息,请查看此处的文档:https://angular.io/guide/component-interaction
路由目标
如果您通过在<router-outlet>
中显示组件作为路由目标,那么就没有“父组件”和“子组件”关系。
在这种情况下,组件之间进行通信的最佳方式是使用服务。
我有一篇关于在此处创建服务的博文:https://blogs.msmvps.com/deborahk/build-a-simple-angular-service-to-share-data/
<强>资源强>
如果您是Angular的新手,通过完成教程或在线课程,您可以节省大量时间和挫折感。这将介绍所有基本概念,以便您快速使用Angular。
您可以在此处完成“英雄之旅”教程:https://angular.io/tutorial
或观看此类课程:https://app.pluralsight.com/library/courses/angular-2-getting-started-update
或者这一个:https://app.pluralsight.com/library/courses/angular-2-first-look/table-of-contents
(您可以注册免费的一周。)
答案 1 :(得分:8)
如果孩子在router-outlet
,您可以使用ContentChild
来调用孩子的方法。所以......
import { ContentChild } from '@angular/core';
在你父母的:
@ContentChild(ChildComponent)
private childComponent: ChildComponent;
并点击您的点击事件:
this.childComponent.doSomething()
您还需要在parent:
中的providers数组中添加子组件@Component({
selector: 'parent',
...
providers: [ChildComponent]
})
答案 2 :(得分:5)
我找到了两种方法来实现这一目标:
<强> 1。将主要成分注入儿童
您可以向主组件添加事件,将主要组件注入子组件并订阅事件。请参阅说明这一点的plunk。但是,现在您的孩子依赖于您的主要组件。这可能不太好。
主要成分
executeAction: EventEmitter<any> = new EventEmitter();
constructor() { }
performAction() {
this.executeAction.emit();
}
子
constructor(private appComponent: AppComponent) {
this.executeAction = this.executeAction.bind(this);
eventSubscriber(appComponent.executeAction, this.executeAction);
}
ngOnDestroy(): void {
eventSubscriber(this.appComponent.executeAction, this.executeAction, true);
}
executeAction() {
alert('1');
}
<强> 2。实施服务
此处和Parent and children communicate via a service中描述的最佳解决方案是创建一个服务,该服务将成为主要组件和子组件之间的附加层。这样,您将独立于主要组件实现。请参阅说明此方法的plunk。
服务
subscription = new Subject();
executeAction() {
this.subscription.next();
}
主要成分
constructor(private appService: AppService) { }
performAction() {
this.appService.executeAction();
}
子
constructor(private appService: AppService) {
this.executeAction = this.executeAction.bind(this);
eventSubscriber(appService.subscription, this.executeAction);
}
ngOnDestroy(): void {
eventSubscriber(this.appService.subscription, this.executeAction, true);
}
executeAction() {
alert('1');
}
答案 3 :(得分:2)
我认为Event emitter可以帮你解决问题
虽然您可以直接在子组件中使用它,但是在这里使用公共服务将是一个很好的做法
首先,您需要在服务中创建类似
的发射器export class EmitterService {
public nameEmitter:EventEmitter<string>=new EventEmitter();
//method to get question
changeName(name:string){
this.nameEmitter.emit(name)
}
}
然后在root组件中注入服务依赖项并调用change name方法来发出更改
constructor(private emitter :EmitterService) {}
this.emitter.changeName("New Name");
最后,子组件订阅了更改
this.emitter.nameEmitter.subscribe(name=>{this.name=name})
这是有效的plunker
答案 4 :(得分:2)
您可以使用shared service与路由器添加的组件进行通信。
您也可以使用路由器插座的activate event让父母知道路由器何时添加了某个组件
<强>模板强>
<router-outlet (activate)="onActivate($event)"></router-outlet>
<强>组件强>
onActivate(componentRef){
componentRef.works();
}
儿童比赛
works(){
console.log("works");
}
答案 5 :(得分:1)
这也可以通过以下方式实现:
.html
<parent>
<router-outlet (activate)="onActivate($event)"><router-outlet>
</parent>
.ts
activatedComponentReference:any
onActivate(activatedComponentReference) {
this.activatedComponentReference = activatedComponentReference;
}
onBtnClick() {
const childRouteComp = this.activatedComponentReference as ChildRouteComponent;
childRouteComp.childFunction();
}
答案 6 :(得分:0)
有两种方法可以从父组件调用路由器出口子组件方法。
ViewChild / ViewChildren - 您可以使用ViewChild / ViewChildren从视图DOM中获取与选择器匹配的元素或指令。路由器插座呈现子组件并不重要。
从'@ angular / core'导入{ViewChild}; @ViewChild(HomeComponent) private childComponent:HomeComponent;
然后你可以调用任何方法,
this.childComponent.changeTitle();
Demo - call router outlet child component method
答案 7 :(得分:0)
在搜索了很多有关此问题的内容之后,我找到了解决方案,希望它可以为您提供帮助。 contentChild / ViewChild无法访问路由器出口中加载的组件(及其数据),并且使用sharedService需要一个额外的文件和更多的代码。
您只需要阅读路由器出口中加载的组件:
将模板参考添加到路由器出口:
<router-outlet #myRouterOutlet ></router-outlet>
从@ angular / router导入RouterOutlet:
import {...
RouterOutlet,
..} from "@angular/router";
最后,使用它:
@ViewChild("myRouterOutlet", { static: true }) routerOutlet: RouterOutlet;
buttonClicked(){
const childComp = this.routerOutlet.component as childComponent;
childComp.childFunction();
}
希望它可以帮助您:)
答案 8 :(得分:0)
尽管这是一个古老的问题,但这里的所有答复都不是完美的。
通过使用服务实例或子实例,您将自己绑定到特定功能 您需要呼叫的名字。服务还会强制您使用依赖项注入。
有一个更好的方法,就是使用一条指令,该指令可以使每一端完全独立 从另一个。
答案 9 :(得分:0)
以上解决方案均未在Angular 10中为我工作。让我与您分享为管理此问题而创建的CustomEventHandler服务:
@Injectable()
export class CustomEventHandler {
private eventHandlersMap: Map<string, Function> = new Map();
constructor() {
}
public callEvent(eventName: string, data?: any): void {
this.eventHandlersMap.get(eventName)(data);
}
public addListener(eventName: string, callback: Function): void {
this.eventHandlersMap.set(eventName, callback);
}
}
您可以在子组件构造函数中添加侦听器,并从父组件调用组件中的任何方法。
// add listener in child component
this.customEventHandler.addListener("some-event", this.someMethodToCall.bind(this));
// call this in parent component
this.customEventHandler.callEvent("some-event");