web-dev-qa-db-ja.com

別のコンポーネントから更新されたときにサービス変数の変更を検出するにはどうすればよいですか?

クリックイベント(isSidebarVisible)で別のコンポーネント(header)によって更新され続けるサービス変数(toggleSidebar)から更新された値を取得しようとしています。

sidebar.service.ts

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

@Injectable() 
export class SidebarService {
    isSidebarVisible: boolean;

    sidebarVisibilityChange: Subject<boolean> = new Subject<boolean>();

    constructor()  {
        this.isSidebarVisible = false;
    }

    toggleSidebarVisibilty() {
        this.isSidebarVisible = !this.isSidebarVisible
        this.sidebarVisibilityChange.next(this.isSidebarVisible);
    }
}

sidebar.component.ts

export class SidebarComponent implements OnInit {
    asideVisible: boolean;
    _asideSubscription: any;

    constructor(private sidebarService: SidebarService) {
        this.asideVisible = sidebarService.isSidebarVisible
        this._asideSubscription = sidebarService.sidebarVisibilityChange.subscribe((value) => {
            this.asideVisible = value
        })
    }

    ngOnInit() {
    }
}

header.component.ts(サービス変数が更新される場所)

export class HeaderComponent implements OnInit {
    isSidebarVisible: boolean;
    _subscription: any;

    constructor(private sidebarService: SidebarService) {
        this._subscription = sidebarService.sidebarVisibilityChange.subscribe((value) => {
            this.isSidebarVisible = value
        })
    }

    toggleSidebar() {
        this.sidebarService.toggleSidebarVisibilty()
    }

    ngOnInit() {

    }
}

header.component.htmlのときに{{ isSidebarVisible }}でサービス変数の値の変化を見ることができますが、sidebar.component.htmlでは常にデフォルト値を出力し、変更をリッスンしませんでした。

これを修正するのを手伝ってください。

33
Body

サブスクリプションをサービスに移動すると、両方のコンポーネントがこの値にアクセスできます。値が1回だけ必要な場合は、直接使用できます(sidebar.componentで行ったように)。この値で何かを更新する必要がある場合は、getterを使用できます(header.componentの例)。

sidebar.service.ts:

@Injectable() 
export class SidebarService {
    isSidebarVisible: boolean;

    sidebarVisibilityChange: Subject<boolean> = new Subject<boolean>();

    constructor()  {
        this.sidebarVisibilityChange.subscribe((value) => {
            this.isSidebarVisible = value
        });
    }

    toggleSidebarVisibility() {
        this.sidebarVisibilityChange.next(!this.isSidebarVisible);
    }
}

sidebar.component.ts

export class SidebarComponent {
    asideVisible: boolean;

    constructor(private sidebarService: SidebarService) {
        this.asideVisible = sidebarService.isSidebarVisible;
    }
}

header.component.ts

export class HeaderComponent {
    constructor(private sidebarService: SidebarService) { }

    get isSidebarVisible(): boolean {
        return this.sidebarService.isSidebarVisible;
    }

    toggleSidebar() {
        this.sidebarService.toggleSidebarVisibility()
    }
}

また、どちらか/両方のコンポーネントでサブジェクトをサブスクライブし、そこで値を取得することもできます。

this.sidebarService.sidebarVisibilityChange.subscribe(value => {...});

サブジェクトについて詳しく知りたい場合は、 こちら をご覧ください。

50
Sasxa