2017-08-16 92 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'應該用於的唯一的東西。 –