How to subscribe service in Angular
Solution 1
isOpen
is a boolean
. A boolean is just a primitive without any publish/subscribe functionality.
What you want is an Observable
that you can actually subscribe to. We'll use a BehaviorSubject
here, as you can give it an initial value.
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/internal/Observable';
import { of } from 'rxjs/internal/observable/of';
@Injectable()
export class ConnectService {
public isOpen$ = new BehaviorSubject(false);
public toggle(): void {
this.isOpen$.next(!this.isOpen$.getValue());
console.log('Im inside toggle');
}
public getIsOpen(): Observable<boolean>{
console.log('Im inside getIsOpen');
return this.isOpen$;
}
}
Then subscribe to it using this.connectService.isOpen$.subscribe(isOpen => ...)
.
Solution 2
of(this.isOpen)
will only emit a value one time. What you need is something like a BehaviorSubject
, which always emits its most recent value.
@Injectable()
export class ConnectService {
public isOpen = new BehaviorSubject<boolean>(false);
public toggle(): void {
this.isOpen.next(!this.isOpen.value);
console.log('Im inside toggle');
}
}
And in your component you can then directly subscribe to your subject, no need to create an additional Observable:
public ngOnInit(): void {
this.connectionService.isOpen.subscribe(x => this.isFirstComponentExpanded = x);
}
Related videos on Youtube
obar
Updated on June 04, 2022Comments
-
obar almost 2 years
i have 3 objects: - first component - connect service - second component
First component when is folded/expanded should expand/fold second component via service.
In service i have function toggle() and it should only change a bool variable of boolean isOpen. Next to it i have other function getIsOpen() with return type Observable. Code looks like this:
import { Injectable } from '@angular/core'; import { Observable } from 'rxjs/internal/Observable'; import { of } from 'rxjs/internal/observable/of'; @Injectable() export class ConnectService { public isOpen = false; public toggle(): void { this.isOpen = !this.isOpen; console.log('Im inside toggle'); } public getIsOpen(): Observable<boolean>{ console.log('Im inside getIsOpen'); return of(this.isOpen); } }
In second component i try to subscribe:
public ngOnInit(): void { this.connectionService.getIsOpen().subscribe(x => this.isFirstComponentExpanded = x); }
But only effect is only after the page load, after click, the second component didn't fold or expand. How to listen every change inside service without event emmiter (i need to avoid any event emitters there, only observables, subscribes and subjects).
-
robert almost 5 yearsCheck this stackblitz
-
obar almost 5 yearsWell, i have same implementation as you and ... not working. Damn ... maybe there is a issue, something else blocking this i think but how :/
-
robert almost 5 yearsCreate a stackblitz from your implementation.
-
obar almost 5 yearsToo many files to add, but i have 1 to 1 and on stackblitz it working fine, have console.logs like i want, inside app is invalid.
-
obar almost 5 yearsMaybe the issue is in location? first component is a part of different module than second
-
obar almost 5 yearsOk guys, someody else added service to providers inside module where is window and this making implementation invalid. Now everything is ok. I think other solutions work's too.
-
-
obar almost 5 yearsProperty 'asObservable' does not exist on type 'Observable<BehaviorSubject<boolean>>'. at return of(this.isOpen).asObservable();
-
Reactgular almost 5 years@obar sorry, I forgot to remove the
of(...)
. I've updated the answer. -
obar almost 5 yearsi tried subscribe like this to code above: this.connectService.isOpen$.subscribe(isOpen => this.firstComponentIsExpanded); and in console i onlt get Im inside toggle (can't get into getIsOpen())
-
obar almost 5 yearsStill can't get into getIsOpen(), console log logging only at page reload
-
fjc almost 5 yearsIf you want to use
getIsOpen
, you need to call it and subscribe to the result:this.connectService.getIsOpen().subscribe(isOpen => this.firstComponentIsExpanded);
-
Reactgular almost 5 years@obar
getIsOpen()
only gets called once. -
obar almost 5 yearsValue isFirstComponentExpanded won't change, i getting log on every click but cant get the value of bool inside service in component.
-
obar almost 5 yearsYes, i wan't to call it multiple times, on every toggle, not only once
-
obar almost 5 yearsSame, only getting im inside toggle. Im inside getIsOpen appear only once after load but i want to appear every time with toggle. If first component toggled service, second component must know about it every time
-
fjc almost 5 yearsThen please share a copy of your application on codepen or similar.
-
obar almost 5 yearsThis is not my first attempt to make it works properly, if i have sample of working code maybe i can understand this, i can't make it with parts of code and every time i failing at this moment :/ Why i can't get into getIsOpen every time? I really need to avoid event emitters inside services.