Angular 4 - @ViewChild 组件未定义
Posted
技术标签:
【中文标题】Angular 4 - @ViewChild 组件未定义【英文标题】:Angular 4 - @ViewChild component is undefined 【发布时间】:2018-01-24 08:53:25 【问题描述】:我有一个名为 ToastComponent
的 toast 通知组件,我想从任何其他组件调用它。我是这样实现的:
ToastComponent
:
export class ToastComponent implements OnInit
constructor()
showToast()
// some code
app.component.html
:
<llqa-main-container>
<llqa-header></llqa-header>
<div class="content-container">
<main class="content-area">
<llqa-toast></llqa-toast> <!-- ToastComponent which I want to call -->
<router-outlet></router-outlet>
</main>
</div>
</llqa-main-container>
UserManagementComponent
在<router-outlet>
内:
export class UserManagementComponent implements OnInit
@ViewChild(ToastComponent) toast: ToastComponent;
constructor()
someSaveMethod()
this.toast.showToast() // throws error below
在调用someSaveMethod()
方法时,我会得到toast
未定义的错误。
如果我从app.component.html
中取出<llqa-toast></llqa-toast>
并将其放在user-management.component.html
之上,它可以正常工作,但是我必须将它放在每个组件中。我怎样才能让它工作?
【问题讨论】:
someSaveMethod
在哪里被调用?尝试使用console.log()
语句检查ToastComponent
的构造函数是否在您调用someSaveMethod
之前被调用。
【参考方案1】:
由于在您的情况下,祖父 (AppComponent
) 中使用了 ToastComponent
,这就是您收到此错误的原因。避免此错误的一种方法是使用在某些共享服务中定义的Subject
。我在我的项目中使用这种方法来显示 toast 通知。以下是你可以做到的:
将您的<llqa-toast></llqa-toast>
保留在app.component.html
中。
定义一个服务以基本上发出一个事件并在您的ToastComponent
中订阅该事件。例如,
实用服务:
import Injectable from '@angular/core';
import Subject from 'rxjs';
@Injectable()
export class UtilityService
public OnShowToast = new Subject<boolean>();
public showToast(): void
this.OnShowToast.next(true);
您需要在您的AppModule
提供程序中注入此服务。现在将subscribe
发送到ToastComponent
中的OnShowToast
事件。
Toast 组件:
import UtilityService from './path/to/the/utility.service';
export class ToastComponent implements OnInit
constructor(private readonly utilityService: UtilityService)
ngOnInit()
this.utilityService.OnShowToast.subscribe(value =>
this.showToast();
);
private showToast()
// some code
现在,您可以从任何您想要的组件调用UtilityService
的showToast()
方法。例如,
用户管理组件
export class UserManagementComponent implements OnInit
// You dont need this now
// @ViewChild(ToastComponent) toast: ToastComponent;
constructor(private readonly utilityService: UtilityService)
someSaveMethod()
this.utilityService.showToast();
【讨论】:
EventEmitter
不应该在服务中使用。 Observable
或 Subject
也是如此。 EventEmitter
应该仅用于@Output()
s。
@GünterZöchbauer 不知道,因为它在我的服务中也没有任何问题。谢谢。在这里更新我的代码以使用 Subject
代替。
目前它正在工作,因为 EventEmitter
只是扩展了 Subject
(AFAIR),但是 Angular 团队可以在不事先通知的情况下将其更改为仍然适用于 @Output()
但可能会破坏其他用途的自定义实现, 因为@Output()
是唯一应该使用EventEmitter
的东西。
@GünterZöchbauer 感谢您提供详细信息,+1以上是关于Angular 4 - @ViewChild 组件未定义的主要内容,如果未能解决你的问题,请参考以下文章
Angular 中的 dom 操作(ViewChild)以及父子组件中通过 ViewChild 调用子组件的方法
带有 viewchild 和指令的 Angular 组件测试
ViewChild 如何在 Angular 和 Storybook 中工作?