I recently wrote a story on using Input s and Output s to pass data back and forth between parent and child components. What if instead of a one-many or many-one parent-child data relationship, we had a many-many relationship. In this case Input s and Output s are not the best option. Instead we can use Subject s.

Rxjs, a reactive programming language, is extremely powerful and has great TypeScript support. At it’s core Rxjs uses observables to let anyone listen to value change from anywhere. Observable is the most basic implementation of listening to data changes, but I find that BehaviorSubject is easier to use and typically has a wider use case. The only difference between BehaviorSubject and Subject is BehaviorSubject has an initial value which will be emitted when subscribed to.

BehaviorSubjects

BehaviorSubject s are imported from the rxjs library, which is standard in a generated Angular project.

// grocery-store.service.ts import { Injectable } from '@angular/core';

import { BehaviorSubject } from 'rxjs'; @Injectable({

providedIn: 'root'

}) export class GroceryStoreService {

private appleBasket: BehaviorSubject<number> = new BehaviorSubject<number>(0);

private limeBasket: BehaviorSubject<number> = new BehaviorSubject<number>(10);

constructor() {} getAppleBasket(): BehaviorSubject<number> {

return this.appleBasket;

} getLimeBasket(): BehaviorSubject<number> {

return this.limeBasket;

}

}

We create a new BehaviorSubject with

private limeBasket: BehaviorSubject<number> = new BehaviorSubject<number>(10);

which simply states that limeBasket is of type number and should be initialized with 10 .

limeBasket has two main methods, subscribe and next . subscribe broadcasts out the value whenever there is a change. next passes a new value into limeBasket therefore triggering subscribe to broadcast. Anyone who has subscribed to limeBasket will receive the value.

// app.component.ts ... constructor(

private groceryStoreService: GroceryStoreService

) { ... this.limesBasket$ = this.groceryStoreService.getLimeBasket(); ... this.limesBasket$.subscribe(value => {

this.lastEvent = `Limes basket now has ${value} limes(s)`;

});

} ...

To emit a new value to the BehaviorSubject we just call next() .

// app.component.ts ... changeLimes() {

this.limesBasket$.next(this.numberOfLimes);

} ...

A great feature about Angular is you can actually avoid subscribing to the BehaviorSubject at all if you only need the subject’s value in your markup.

// lime.component.html <div class="container">

Number of limes: {{ limesBasket$ | async }}

</div>

The async pipe is out of the box with Angular and basically says, “hey, this is a some type of observable so subscribe for me and put the value here.”

Notes

Make sure to include your service as a provider inside app.module.ts .

. Adding a $ at the end of a property/variable, limeBasket$ , is a general convention used for denoting observable types.

Summary

BehaviorSubject s are a great way to pass data back forth between a large number of components. The two main methods are subscribe , for listening to new values, and next , for setting new values.

Check out my example on Github: https://github.com/orange-bees/angular-concepts-tutorials.

About Me

I work for Orange Bees, an enterprise software engineering company in Greenville, SC, as a Principal Frontend Engineer. I mostly write Angular applications, but dabble in some Node.js, Vue.js and ElasticSearch.

You can find me on LinkedIn.