Как я могу обнаружить изменение служебной переменной при обновлении из другого компонента?

Я пытаюсь получить обновленное значение из служебной переменной (isSidebarVisible), которая продолжает обновляться другим компонентом (header) с событием click (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 }}, но In sidebar.component.html всегда печатает значение по умолчанию и никогда не прослушивает изменения.

Пожалуйста, помогите мне исправить это.

Ответ 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 => {...});

Если вы хотите узнать больше о предметах, посмотрите здесь.

Ответ 2

Пожалуйста, объясните, почему мы подписываем тему изнутри сервиса, поскольку я не могу понять эту концепцию как новичок!