2017-04-22 3 views
0

Ich versuche, das Singleton-Entwurfsmuster zu implementieren, indem Sie einen freigegebenen Dienst verwenden, damit alle Komponenten die aktualisierte globale Variable empfangen können, die von dem Dienst bereitgestellt wird.Angular Shared Service - Abonnieren übergibt undefined zu Komponente

Das Ergebnis ist, dass es ohne Probleme aktualisieren, wenn sie von App-Komponente aufgerufen, aber keine Komponente erhält den Wert, wenn Subcribing an:

colorString$ = this.colorSource.asObservable(); 

Die verwendete Methode zur Zeichnung, die nicht einen Wert zurückgegeben:

constructor(private sharedSer : SharedColorService) { 
    sharedSer.Update(this.myColor); 
    } 

Dies ist der Service:

import {Injectable} from '@angular/core'; 
import { Subject } from 'rxjs/Subject'; 

@Injectable() 
export class SharedColorService { 

    // Observable string source 
private colorSource = new Subject<string>(); 

// Observable string stream 
colorString$ = this.colorSource.asObservable(); 

// Service message commands 

Update(input:string) { 
    this.colorSource.next(input); 
    console.log("Service Color: " + input); 
} 
} 

Dies ist die App .component:

import { Component, OnInit } from '@angular/core'; 
import {SharedColorService} from './sharedColor.service'; 

@Component({ 
    selector: 'app-root', 
    templateUrl: './app.component.html', 
    styleUrls: ['./app.component.css'] 
}) 
export class AppComponent { 
    colors = ["#31b0d5", "#d55631", "#d531b0", "#31d556"] 
    myColor = this.colors[Math.floor(Math.random()*this.colors.length)]; 

    constructor(private sharedSer : SharedColorService) { 
    console.log("I can log"); 
    console.log("App Color: " + this.myColor); 
    sharedSer.Update(this.myColor); 
    } 
    } 

Dies ist die Komponente, die die App Komponente Lasten:

app.component.html:

<h1>APP: {{myColor}}</h1> 
<app-navigation></app-navigation> 

navigation.component

import { Component, OnInit, Injectable } from '@angular/core'; 
import {SharedColorService} from '../sharedColor.service'; 
@Component({ 
    selector: 'app-navigation', 
    templateUrl: './navigation.component.html', 
    styleUrls: ['./navigation.component.css'], 
}) 

export class NavigationComponent{ 
    myColor: string; 
    errors; 
    constructor(private _sharedService: SharedColorService){ 
    console.log("I AM TRYING TO SUBSCRIBE"); 
    this._sharedService.colorString$.subscribe(
    result => { 
     console.log('Navigation received result: ', result); 
     this.myColor = result; 
     }); 
     console.log('Navigation after subscribe: ', this.myColor) 
    } 
} 

Und schließlich I einen Routerausgang haben, der von der Navigation geladen wird:

navigation.component.html

<a class="col-sm-2" routerLink="/about" routerLinkActive="active">About</a> 
<router-outlet></router-outlet> 

about.component

import { Component, OnInit } from '@angular/core'; 
import {SharedColorService} from '../sharedColor.service'; 

@Component({ 
    selector: 'app-about', 
    templateUrl: './about.component.html', 
    styleUrls: ['./about.component.css'] 
}) 
export class AboutComponent implements OnInit { 

myColor: string; 
constructor(private _sharedService: SharedColorService){} 

ngOnInit() { 
    this._sharedService.colorString$.subscribe(
    data => { 
     this.myColor = data; 
      console.log("About received color: " + this.myColor + " Data: " + data); 
    }); 
} 
} 

Der Ausgang der Konsole mit all der Protokollierung, wenn die Seite geladen ist:

I can log 
app.component.ts:15 App Color: #31d556 
sharedColor.service.ts:16 Service Color: #31d556 
navigation.component.ts:15 I AM TRYING TO SUBSCRIBE 
navigation.component.ts:21 Navigation after subscribe: undefined 

Wenn über den Zugriff, es ist nicht angerufen, um entweder zu abonnieren - Ich verstehe noch nicht den Lebenszyklus des Router Outlet in Bezug auf OnInit und seine Konstruktoren.

+0

Mögliche Duplikat [Angular 2 - Daten und Rück direkt von einer beobachtbaren] (http://stackoverflow.com/questions/37867020/angular-2-return-data-directly-from-an- observessable) – jonrsharpe

+0

Beachten Sie auch, dass Sie abonnieren, nachdem der Wert geändert wurde, aber ein Vanilla 'Subject' wird keine alten Werte wiedergeben für neue Abonnenten. – jonrsharpe

+0

Danke für den Link, BehaviorSubject funktioniert. –

Antwort

0

Es funktioniert nun ein Verhalten Gegenstand statt eines Motivs mit:

import {Injectable} from '@angular/core'; 
import { Subject } from 'rxjs/Subject'; 
import {BehaviorSubject} from 'rxjs/BehaviorSubject'; 

@Injectable() 
export class SharedColorService { 

    // Observable string source 
private colorSource: BehaviorSubject<string>= new BehaviorSubject<string>("#d55631"); 

// Observable string stream 
colorString$ = this.colorSource.asObservable(); 

// Service message commands 
Update(input:string) { 
    this.colorSource.next(input); 
    console.log("Service Color: " + input); 
} 

} 

console.log

app.component.ts:14 I can log 
app.component.ts:15 App Color: #31b0d5 
sharedColor.service.ts:17 Service Color: #31b0d5 
navigation.component.ts:13 I AM TRYING TO SUBSCRIBE 
navigation.component.ts:16 Navigation received result: #31b0d5 
navigation.component.ts:19 Navigation after subscribe: #31b0d5 
core.es5.js:3025 Angular is running in the development mode. Call 
about.component.ts:18 About received color: #31b0d5 Data: #31b0d5 
Verwandte Themen