Reputation: 687
I am trying to use a service in Angular that holds the state of the application in a string variable. I am using RxJS to use BehaviorSubject, and then my components subscribe to an observable of the BehaviorSubject.
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
import { Injectable } from '@angular/core';
@Injectable()
export class StateService {
private sourceState = new BehaviorSubject<string>('Default State');
currentState = this.sourceState.asObservable();
constructor() { }
setState(state: string) {
this.sourceState.next(state);
console.log(this.currentState);
}
}
My components all subscribe to this observable during the NgOnInit lifecycle.
import { Component, OnInit } from '@angular/core';
import { AuthService } from '../../services/auth.service';
import { StateService } from '../../services/state.service';
import { Router } from '@angular/router';
import 'rxjs/add/operator/filter';
import { Location } from '@angular/common';
@Component ({
selector: 'app-nav',
templateUrl: './nav.component.html',
styleUrls: ['./nav.component.scss'],
providers: [StateService]
})
export class NavComponent implements OnInit {
currentState: string;
constructor(
private authService: AuthService,
private router: Router,
private stateService: StateService
) {}
ngOnInit() {
this.stateService.currentState.subscribe(
state => (this.currentState = state)
);
}
logout() {
this.authService.logout();
}
changeState(state: string) {
this.stateService.setState(state);
}
}
Other components in my application will call the setState function in the state.service.ts file. I am binding the state value in my template just to watch the value so I can then use directives to change the experience based on application state.
Values in the components are not changing even though when I console.log the observable I can see it is being set correctly.
When I call the setState function within the nav component I do see the value of the string interpolation change but only in the nav.component.ts, other components will not change. It is almost like they are using clones of the observable.
<nav class="navbar" [ngClass]="{red: currentState==='stove'}">
<a class="navbar-brand" routerLink="/app">
<img src="../assets/img/app/back.svg" alt="">
</a>
<ul class="nav justify-content-end">
<li class="nav-item">
<a class="nav-link active" routerLink="/login" (click)="logout()">Logout
<i class="fa fa-sign-out" aria-hidden="true"></i>
</a>
</li>
</ul>
</nav>
{{ currentState }}
Upvotes: 0
Views: 1972
Reputation: 6842
The problems is related to this,
@Component ({
selector: 'app-nav',
templateUrl: './nav.component.html',
styleUrls: ['./nav.component.scss'],
providers: [StateService]
})
You are providing the service in the component, that means you are not getting a singleton instance of it. Check this answer that is related.
You have to use the NgModule providers array, and remove it from the component's array provider.
@NgModule({
...
providers: [StateService],
...
})
Upvotes: 6