I would use the Observable.zip
operator:
About zip operator
What you need to do first is to convert your focus event to an observable
using Observable.fromEvent
, then use the zip
operator along with filter
like this:
Observable.zip(Observable.fromEvent(focusEvent),
behaviourSubjectOne.asObservable(),
behaviourSubjectTwo.asObservable())
.filter((arrayOfResults) => !arrayOfResults.some((val) => val === false))
.subscribe(() => {
// all three conditions are fulfilled, do what you need here
});
EDIT:
After some revision, I came to this plunk:
https://plnkr.co/edit/spNldiSb1WwgmrHrB6u1
Posting the code if plunker ever is lost(omitting HTML):
export class App {
name:string;
output: string = '';
subjectOne: BehaviorSubject <boolean> = new BehaviorSubject <boolean>(false);
subjectTwo: BehaviorSubject <boolean> = new BehaviorSubject <boolean>(false);
constructor() {
this.name = `Angular! v${VERSION.full}`;
Observable.combineLatest(Observable.merge(Observable.fromEvent(window, 'focus').map((ev) => 'focus'),
Observable.fromEvent(window, 'blur').map((ev) => 'blur')).startWith('blur'),
this.subjectOne.asObservable(),
this.subjectTwo.asObservable())
.map((state) => [state[0] === 'focus', state[1], state[2]])
// filter would go here
.subscribe((array) => {
this.output = JSON.stringify(array);
});
}
}
This is a complicated observable chain, but I will try to explain what I did:
First of all I used the combineLatest operator to enable listening to changes of state of the three booleans. As the first parameter I passed the merged observables of the focus and the blur event. Since only one can fire at a time this always gives the current state of the window. StartWith was given for an initial state. Then the subjects were passed in.
Then I mapped it to an array on which the OP can apply the filter above.