2016-06-25 5 views
11

Ich habe ein Problem mit einem Abonnement für eine beobachtbare nicht auslösende.Angular 2 Observable Subscription nicht triggern

Ich habe ein Layout der Seite nav Layout Richtlinie wie folgt aussehen mit:

<md-sidenav-layout class="nav-bar"> 


    <md-sidenav #start> 
     <nav> 
      <a [routerLink]="['/home']">Home</a> 
     </nav> 
     <button md-button (click)="start.close()">Close</button> 
    </md-sidenav> 

    <router-outlet></router-outlet> 

</md-sidenav-layout> 

Was muss ich offen tun, ist die Seite nav von der Komponente, die der Router-Ausgang anzeigt wird.

Eine solche Komponente könnte wie folgt aussehen:

@Component({ 

    providers: [SidenavService, MdIconRegistry], 
    directives: [MdIcon], 
    templateUrl: `<md-icon (click)="toggleSidenav()">menu</md-icon>`, 
    styleUrls: ["./home.component.scss"] 
}) 

export class Home { 

    myColor: string; 

    constructor(private sidenavService: SidenavService) { 
     this.myColor = "primary"; 

     this.sidenavService.getSidenavObs().subscribe(state => {console.log("state change")}); 
    } 


    toggleSidenav() { 

     this.sidenavService.toggleSidenav("open"); 
    } 

} 

Ich habe einen Dienst geschaffen, die eine beobachtbare wie folgt zurück:

@Injectable() 
export class SidenavService { 

    private toggle = new Subject<string>(); 
    private toggleObs = this.toggle.asObservable(); 

    getSidenavObs() { 
     return this.toggleObs; 
    } 

    toggleSidenav(state: string) { 
     this.toggle.next(state); 
    } 

} 

Schließlich wird der Code für die Elternklasse (das mit der gehört Seite nav Layout HTML):

@Component({ 
    providers: [MdSidenav, SidenavService], 
    directives: [ROUTER_DIRECTIVES, MD_SIDENAV_DIRECTIVES, MD_BUTTON_DIRECTIVES], 
    selector: "app", 
    templateUrl: "app.html", 
    styleUrls: ["./app.scss"], 
}) 

export class App { 

    subscription: Subscription; 

    constructor(private sidenavService: SidenavService, private sidenav: MdSidenav) { 
    this.subscription = sidenavService.getSidenavObs().subscribe(status => { 
     console.log("state change"); 
     sidenav.open(); 
    }, error => { 
     console.log(error); 
    },() => { 
     console.log("completed"); 
    }); 
    } 
} 

Jetzt ist mein Problem, dass das Abonnement in Die App-Komponente löst jedoch nicht aus, dass das Abonnement in der Home-Komponente (was der Router-Ausgang anzeigt) wie erwartet ausgelöst wird.

Fehle ich hier etwas?

folgte ich diese Anleitung: https://angular.io/docs/ts/latest/cookbook/component-communication.html#!#bidirectional-service

Antwort

49

Der gleiche Service-Instanz nicht werden über Ihre App und Home Komponenten gemeinsam genutzt wird, weil Sie SidenavService als Anbieter für beide aufgeführt haben.

Wenn Sie den Dienstanbieter im Eintrag providers10 eines Komponentendekorators definieren, ist dieser Dienst dann für diese Komponente und alle untergeordneten Elemente als Singleton verfügbar. Dies bedeutet, dass dieselbe Instanz des Dienstes verwendet wird.

Wenn Sie einen Provider in einer untergeordneten Komponente neu definieren, wird eine neue Instanz des Service erstellt und wird nicht mehr dieselbe Service-Instanz wie die übergeordneten/übergeordneten haben.

Wenn Sie SidenavService in beiden App-und Home-Komponenten und benötigen die gleiche Instanz verwenden, sollten Sie es nur in der Komponente App zur Verfügung stellen und sie aus dem providers Eintrag von zu Hause entfernen.

Für weitere Informationen über DI, eine Lese der folgenden Links: https://angular.io/docs/ts/latest/guide/dependency-injection.html https://angular.io/docs/ts/latest/guide/hierarchical-dependency-injection.html

+0

Vielen Dank! Das hat mein Problem gelöst. – mda144

+1

Danke Michael! – Leibniz

+0

Danke Michael !! Du hast mich gerettet – bews99