2017-05-26 94 views
0

我想從我的共享服務調用sidenav組件的方法open()。如果我直接從組件調用方法,它工作正常。但只要我調用相同的方法從共享服務我有一個錯誤消息:從共享服務調用組件的方法

ERROR TypeError: Cannot read property 'open' of undefined

Sidenav組分:

import { MdSidenav } from '@angular/material'; 
import { Component, OnInit, ViewChild } from '@angular/core'; 

@Component({ 
    selector: 'app-sidebar-content', 
    template: ` 
    <md-sidenav-container class="container"> 
    <md-sidenav #sidenav class="sidenav"> 
     Jolly good! 
    </md-sidenav> 

    <app-main-content></app-main-content> 

    </md-sidenav-container> 
    `, 
    styleUrls: ['./sidebar-content.component.css'] 
}) 
export class SidebarContentComponent implements OnInit { 

    @ViewChild('sidenav') el: MdSidenav; 

    constructor() { } 

    ngOnInit() { 

    } 

    openSideNav() { 
    this.el.open();  
    } 

} 

共享服務:

import { SidebarContentComponent } from './../content/sidebar-content/sidebar-content.component'; 
import { Injectable } from '@angular/core'; 


@Injectable() 
export class SharedService { 

    constructor(private sc: SidebarContentComponent) { } 

    openSidenav() { 
    this.sc.openSideNav(); 
    } 

} 

從另一個組件調用開放方法:

import { SharedService } from './../../services/shared.service'; 
import { Component, OnInit } from '@angular/core'; 

import { SidebarContentComponent } from './../sidebar-content/sidebar-content.component'; 

@Component({ 
    selector: 'app-main-content', 
    templateUrl: ` 
    <div class="sidenav-content"> 
     <app-toolbar></app-toolbar> 
     <button md-button (click)="open()"> 
     Open sidenav 
     </button> 
     <button md-button (click)="openWithService()"> 
     Open sidenav with service 
     </button> 
    </div> 
    `, 
    styleUrls: ['./main-content.component.css'] 
}) 
export class MainContentComponent implements OnInit { 

    constructor(private sc: SidebarContentComponent, private ss: SharedService) { } 

    ngOnInit() { 
    } 

    open() { 
    this.sc.openSideNav(); 
    // Works fine 
    } 

    openWithService() { 
    this.ss.openSidenav(); 
    // Throws an error 
    // ERROR TypeError: Cannot read property 'open' of undefined 
    } 

} 
+0

您沒有設置服務的SidebarContentComponent,這就是爲什麼它小號並且它是未定義的。將它放在構造函數中不起作用:它可以是任何SidebarContentComponent,即使您可能只有一個。 – Ploppy

+1

設計是錯誤的。服務被注入組件,反之亦然。你不能將一個組件注入到服務中。從技術上講,你可以這樣做,因爲組件是可注入類,但它不能正常工作,就像我們在這裏看到的那樣。 – estus

+0

@estus我認爲在這種情況下正確的做法是使用rxjs /主題並讓服務將方法調用傳播給它的訂閱者。 – Ploppy

回答

1

您沒有設置您的服務的SidebarContentComponent。即使你可以這樣做,我認爲正確的方法是使用rxjs/Subject。

這應做到:

SharedService

import { Subject } from 'rxjs/Subject'; // don't forget to import it! 

public open$: Subject<any> = new Subject(); 

SidenavComponent

this.sharedService.open$.subscribe(() => this.openSideNav()); 

AnyComponent

this.sharedService.open$.next(); 
+0

我不知道爲什麼我得到'未捕獲的錯誤:無法解析SidebarContentComponent的所有參數:(?)。'error – Gabriel

+0

我不認爲它與我的代碼有關。這個錯誤位於哪裏? – Ploppy

+0

它在SidenavComponent中。爲了澄清,我需要將服務注入到Sidenav組件中,然後在ngOnInit鉤子中訂閱主題? – Gabriel