2017-08-10 13 views
1

異なるコンポーネントで呼び出されたオブザーバに登録する際に問題が発生しています。他のコンポーネントまたはサービスとのオブザーバを共有する

My Angular 4アプリには、ユーザー情報の一部を含むナビゲーションバーがあります。ユーザー情報は、ログイン時にサーバーへのhttp要求から取得されます。これはLoginServiceで管理されます。ログアウト時に、ユーザーをnullに設定しました。

logIn() { 
    return this.http 
    .get(this.apiUrl) 
    .map(response => response.json()) 
} 

logOut() { 
    return Observable.of(null) 
} 

ログインコンポーネントから、サービスを使用してユーザーの詳細を取得するのはかなり簡単です。

logIn() { 
    this.loginService.logIn().subscribe((user) => { 
    console.log('Logged in') 
    this.user = user 
    console.log(this.user) 
) 
} 

しかし、別のコンポーネントから取得して、navbarに値を設定する必要があります。 Navbarコンポーネントを使用してLoginServiceのlogIn()およびlogOut()関数を登録し、これらのオブザーバブルをマージし、いずれかのイベントがトリガされた場合はそのユーザを更新する必要があると思います。しかし、私はそれらを購読することはできませんし、2日後に私はまだこれに固執しています。

I've made a plunk to show the problem。ログインボタンをクリックすると、app.componentのユーザーを設定する必要があります。ログアウトボタンをクリックすると、設定を解除する必要があります。

+0

我々はサービスがの観測可能に公開したパターンを使用していた

は、あなたが更新されplnkrを参照してください。現在の状態とその状態を更新するいくつかの方法については、http://blog.jonrshar.pe/2017/Apr/09/async-angular-data.htmlを参照してください。私は関連する質問に関するテクニックを示す答えも書いています:https://stackoverflow.com/a/41554338/3001761 – jonrsharpe

答えて

3

を私はちょうどBehaviorSubjectの代わりに使用したいですユーザをプロパティとしてLoginServiceに保ちます。それで、あなたは現在のユーザーが必要なときはいつでもそれを購読することができます。ログアウトは、ちょうど.next(null)を呼んでいる:テンプレートhttps://plnkr.co/edit/soeqH4IiNhcanNqxdnLS?p=preview

LoginService

@Injectable() 
export class LoginService { 
    private apiUrl = 'https://api.github.com/users/geraintanderson' 

    user$ = new BehaviorSubject(null); 

    constructor(
    private http: Http 
) {} 

    logIn() { 
    return this.http 
     .get(this.apiUrl) 
     .map(response => response.json()) 
     .do(user => this.user$.next(user)) 
    } 

    logOut() { 
    this.user$.next(null); 
    } 
} 

<span *ngIf="loginService.user$ | async; else noUser; let user"> 
    Logged in as <b>{{ user.name }}</b> 
</span> 
<ng-template #noUser><span>Not logged in</span></ng-template> 
+0

私は、被験者を直接公開しないことを推奨します。これは、サービスの他の消費者がデータをストリーム。 – jonrsharpe

+0

@jonrsharpe確かに、私はそれを書き直すにはあまりにも怠惰でした。 – martin

+0

より単純なソリューションが利用可能なときに、なぜ複雑なBehaviorSubjectソリューションを使用するのですか? 'BehaviorSubject'は不必要に大過剰に使いすぎているようです。 – DeborahK

1

もっと簡単な解決策は、観測可能性を公開するのではなく、データを公開することです。私はここにあなたのplunkerを更新しました:https://plnkr.co/edit/ilfEtmxolC16vRKRiE0q?p=preview

をサービス:

import { Injectable } from '@angular/core' 
import { Http } from '@angular/http' 

import 'rxjs/add/operator/map' 

@Injectable() 
export class LoginService { 
    user; 

    private apiUrl = 'https://api.github.com/users/geraintanderson' 

    constructor(
    private http: Http 
) {} 

    logIn() { 
    return this.http 
    .get(this.apiUrl) 
    .map(response => response.json()) 
    .subscribe((user) => { 
     console.log('Logged in') 
     this.user = user 
     console.log(JSON.stringify(this.user)); 
    ) 
    } 

    logOut() { 
    this.user = null; 
    console.log('Logged out') 
    } 
} 

コンポーネント:

import {Component, OnInit, VERSION} from '@angular/core' 
import { LoginService } from './login.service' 

@Component({ 
    selector: 'my-app', 
    templateUrl: './src/app.component.html', 
}) 
export class App implements OnInit { 
    get user() { 
    return this.loginService.user; 
    } 

    constructor(private loginService: LoginService) { 
    this.angularVersion = `Angular version ${VERSION.full}` 
    } 
} 

HTML:

<div> 
    <span *ngIf="user">Logged in as <b>{{user.name}}</b></span> 
    <span *ngIf="!user">Not logged in</span> 
    <h2>Shared services</h2><p>Created with {{angularVersion}}</p> 
    <hr> 
    <app-login></app-login> 
</div> 
関連する問題