Reputation: 105
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).
Upvotes: 4
Views: 25400
Reputation: 54821
You can use a BehaviorSubject()
@Injectable()
export class ConnectService {
public isOpen = new BehaviorSubject(false);
public toggle(): void {
this.isOpen.next(!this.isOpen.getValue());
}
public getIsOpen(): Observable<boolean> {
return this.isOpen.asObservable();
}
}
Upvotes: 0
Reputation: 5825
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 => ...)
.
Upvotes: 3
Reputation: 1637
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);
}
Upvotes: 7