BehaviorSubject and conditional Component display

988 views Asked by At

I've got this simple Service:

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

@Injectable()
export class HighlightsService {
  private _highlitTab: string = '';
  highlitTab$: BehaviorSubject<string> = new BehaviorSubject(this._highlitTab);

  public get tab(): string {
    return this._highlitTab;
  }

  public set tab(val: string) {
    this._highlitTab = val;
    this.highlitTab$.next(this._highlitTab);
  }
}

Which is set in my tabs:

(select)="highlightsService.tab = 'show component0'

Now in my view which shows multiple directives, how do I conditionally show them?

<app-component0 [hide]="highlightsService.highlitTab$ | async"></app-component0>
<app-component1 [show]="highlightsService.highlitTab$ | async"></app-component0>

Obviously that won't work, because there's no ===. Is there some ngSwitch equivalent?

How do I conditionally show Components based on BehaviourSubject value?

2

There are 2 answers

2
trey-jones On

First of all, I don't think that async pipe will work with just BehaviorSubject anyway. This is how I would do it:

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

@Injectable()
export class HighlightsService {
  private _highlitTab: string = '';
  private _highlitTab$: BehaviorSubject<string> = new BehaviorSubject(this._highlitTab);
  public highlitTab$: Observable<string> = this._highlitTab$.asObservable();

  public get tab(): string {
    return this._highlitTab;
  }

  public set tab(val: string) {
    this._highlitTab = val;
    this._highlitTab$.next(this._highlitTab);
  }
}

The value of the _highlitTab variable is also questionable because you can get it within the service with this._highlitTab$.getValue().

Now, in your component, you inject the HighlightsService as you seem to already be doing, and subscribe to it, probably in ngOnInit():

this.highlightsService.highlitTab$
    .filter(value => value)
    .subscribe(value => this.hightlitTab = value);

The filter line ensures that you don't get an empty value (the initialization value). This may not be your desired behavior.

Finally, you can now show or hide whichever tab you want by comparing it to the updated local value of highlitTab. If it were me, I probably just pass the highlitTab value on down to the child component, and that component can decide whether to show itself or not.

<child-component0 [highlitTab]='hightlitTab'></child-component>
0
A T On

Ended up moving the tab checking logic to the Service. Now my Components don't need to subscribe.