T.Aoukar T.Aoukar - 1 month ago 20
TypeScript Question

Angular 4 Observable returning undefined

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??

Answer Source

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.