Bromox
Bromox

Reputation: 687

Observable value is not updating

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.

State.Service.ts

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.

Nav.component.ts

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.

The Problem

Values in the components are not changing even though when I console.log the observable I can see it is being set correctly.

Note

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.component.html

<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

Answers (1)

Luillyfe
Luillyfe

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

Related Questions