将元素绑定到Angular服务中的BehaviorSubject

时间:2017-04-10 12:52:59

标签: angular typescript rxjs observable

我有一个小的共享Angular服务,如下所示:

import {Injectable} from '@angular/core';
import {BehaviorSubject, Observable} from 'rxjs/Rx';

@Injectable()
export class SidebarService {
    private _isOpen: BehaviorSubject<boolean> = new BehaviorSubject(false);

    constructor() {
        this._isOpen.subscribe(val => {
            console.log(`isOpen: ${val}`);
        });
    }

    public get isOpen() {
        return this._isOpen.asObservable();
    }

    toggle() {
        this._isOpen.next(!this._isOpen.getValue());
    }
}

我想将.isOpen属性绑定到视图中的元素。我目前正在使用以下代码段在视图中尝试绑定:

<p>Sidebar State: {{sidebarService?.isOpen | async}}</p>

该属性最初是绑定的,但不响应连续的更改。在SidebarService中调用侧边栏toggle()方法时,我想要的是侧边栏状态:更新。

有什么想法吗?

1 个答案:

答案 0 :(得分:4)

问题是由于SidebarService的多个实例正在运行。

我通过将@Component装饰器中的提供程序的声明从共享SidebarService的两个组件移动到 app.module.ts 来修复此问题,如下所示:

@NgModule({
    declarations: [
        // ...
        SidebarComponent,
        // ...
    ],
    imports: [ /* ... */ ])
    ],
    // Line below was duplicated in two components,
    // causing multiple instances...
    providers: [SidebarService], // <--
    bootstrap: [AppComponent]
})

这意味着我的绑定一起观察Observable的整个不同实例的变化。

我还发现.asObservable()调用完全没必要,因此生成的SidebarService现在看起来如下:

import {Injectable} from '@angular/core';
import {BehaviorSubject, Observable} from 'rxjs/Rx';

@Injectable()
export class SidebarService {
    private _isOpen: BehaviorSubject<boolean>;

    constructor() {
        this._isOpen = new BehaviorSubject(true);
    }

    public get isOpen() {
        return this._isOpen;
    }

    toggle() {
        this._isOpen.next(!this._isOpen.getValue());
    }
}