2017-08-16 66 views
1

我有一个名为ToastComponent的烤面包通知组件,我想从任何其他组件调用。我实现这样的:Angular 4 - @ViewChild组件未定义

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之上,它可以正常工作,但我必须将它放在每个组件中。我怎样才能使这个工作?

+2

凡'someSaveMethod'被称为?尝试使用'console.log()'语句来检查在调用'someSaveMethod'之前是否调用了'ToastComponent'的构造函数。 –

回答

3

因为您的情况,ToastComponent用于父母(AppComponent),这就是为什么你会得到这个错误。避免此错误的一种方法是使用在某些共享服务中定义的Subject。我在我的项目中使用这种方法来显示吐司通知。这里是你如何能做到这:


让您在<llqa-toast></llqa-toast>app.component.html

定义一项服务,基本上发出一个事件并订阅您的ToastComponent中的事件。例如,

UtilityService:

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事件。

ToastComponent:

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 
    } 
} 

现在,你可以从任何你想要的组件调用UtilityServiceshowToast()方法。例如,

UserManagementComponent

export class UserManagementComponent implements OnInit { 

    // You dont need this now 
    // @ViewChild(ToastComponent) toast: ToastComponent; 

    constructor(private readonly utilityService: UtilityService) {} 

    someSaveMethod() { 
    this.utilityService.showToast(); 
    } 
} 
+1

'EventEmitter'不应该用于服务。一个'Observable'或'Subject'也一样。 'EventEmitter'应该只用于** @Output()。 –

+0

@GünterZöchbauer不知道,因为它在我的服务中也没有任何问题。谢谢。在这里更新我的代码以代替使用'Subject'。 – Faisal

+1

由于'EventEmitter'只是扩展了'Subject'(AFAIR),但目前它正在工作,但是Angular团队可以在没有事先通知的情况下改变这个自定义实现,它仍然适用于'@Output()',但可能会破坏其他用途, Output()'是'EventEmitter'应该用于的唯一的东西。 –