1

First things first, this isn't related to some http request, it's way much simpler scenario where a components sets a boolean value and another component display/hide element based on it.

The problem is that the other component always receives 'undefined' in the subscribe call back. However, I tried to make the main component subscribe as well, and it's receiving the value correctly.

Here's my code:

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

@Injectable()
export class EnablerService {
  private _enabled= new Subject<boolean>();
  get Enabled() { return this._enabled.asObservable(); }
  SetEnabled(value: boolean) {
    this._enabled.next(value);
    console.log(`service: ${value}`);
  }
}

main component:

import { Component } from '@angular/core';
import {EnablerService} from './enabler.service';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
  providers: [EnablerService]
})

export class AppComponent {
  title = 'app';
  private _isEnabled: boolean;
  constructor(public service: EnablerService) {
    service.Enabled.subscribe(val => {
         this._isEnabled = val; 
         console.log(`app comp: ${this._isEnabled}`); 
    });
  }

  Switch() {
    this.service.SetEnabled(!this._isEnabled);
    console.log('switched');
  }
}

other component:

import { Component, OnInit } from '@angular/core';
import {EnablerService} from './enabler.service';

@Component({
  selector: 'app-footer',
  templateUrl: './footer.component.html',
  styleUrls: ['./footer.component.css'],
  providers: [EnablerService]
})
export class FooterComponent implements OnInit {
  private _isEnabled: boolean;
  constructor(private service: EnablerService) {
    this._isEnabled = true;
  }

  ngOnInit() {
    this.service.Enabled.subscribe(val => {
      this._isEnabled = val; // this one here.
      console.log(`footer comp: ${this._isEnabled}`);
    });
  }

}

The main component binds Switch method to a button, and it works. The console outputs this on click:

app comp: true

service: true

switched

undefined

clicking again will switch the true values to false but still gives undefined.

Anyone has an idea what's going on here??

Community
  • 1
  • 1
T.Aoukar
  • 653
  • 5
  • 19

1 Answers1

4

When you put your EnablerService in component's providers array, it would receive new instance of the service, while you need to share one between your components. You should provide EnablerService in some parent component only (maybe AppRoot component) and use it (inject it) in child components.

See docs for a sample usage: only MissionControlComponent has MissionService listed in providers, AstronautComponent does not - it has it just injected.

tdragon
  • 3,209
  • 1
  • 16
  • 17
  • It works now, thanks for the answer, didn't notice that I only needed to register it as provider once only. – T.Aoukar Sep 25 '17 at 15:51
  • I had the same issue once :) The idea is shortly described here: https://angular.io/guide/architecture#dependency-injection. – tdragon Sep 25 '17 at 15:57
  • shouldn't we only inject the service in providers app.module , and no need to inject it again as provider in every components – Amr.Ayoub Nov 22 '17 at 21:22