Jul
19
Written by:
Michael Washington
7/19/2017 8:12 PM
You can use BehaviorSubject to facilitate communication between Angular components.
You will find this useful for the following scenarios:
- If a component needs to send or receive a value from one of more components
- If a component needs to pass a value to another component that it is not directly connected to
The Sample
The sample code (available on the Downloads page of this site), allows you to select one of the counter pages, and provides a Increment button for you to click.
When you click the Increment button, the counter number display in both the Page Header, and on the component, will increment.
If you switch to another Counter page, it will pick up the count, and also increment it, when it’s button is clicked.
The Code
In the counter.service.ts file, we set the _count field as a BehaviorSubject and declare it as a number with an initial value of 0.
Next we define setCount and getCount methods.
The setCount method allows the _count to be set and then .Next is called, which will push its value out to any component that is subscribed to it through the getCount method (where _count is exposed as an Observable).
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
// See: BehaviorSubject vs Observable?
// https://stackoverflow.com/questions/39494058/behaviorsubject-vs-observable
@Injectable()
export class CounterService {
private _count = new BehaviorSubject<number>(0);
setCount(paramCount: number) {
this._count.next(paramCount);
}
getCount(): Observable<number> {
return this._count.asObservable();
}
}
The app.component.ts file contains the code for the main page of the application.
In its ngOnInit method, we subscribe to the CounterService and set the local variable (Counter) to its value.
This value will be automatically updated whenever it changes in the service.
Note that we implement ngOnDestroy to remove any subscriptions (to prevent any memory leaks).
import { Component, OnInit, OnDestroy } from '@angular/core';
import { Subscription } from 'rxjs/Subscription';
import { MenuItem } from 'primeng/primeng';
import { CounterService } from '../services/counter.service';
@Component({
selector: 'app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit, OnDestroy {
MenuItems: MenuItem[];
CounterSubscription: Subscription;
Counter: number;
constructor(private _CounterService: CounterService) { }
ngOnInit() {
// Subscribe to the Counter service
this.CounterSubscription = this._CounterService.getCount().subscribe(
(count: number) => {
this.Counter = count;
});
}
ngOnDestroy(): void {
// Important - Unsubscribe from any subscriptions
this.CounterSubscription.unsubscribe();
}
}
We then open up the app.component.html file and add the following code to display the value for the Counter variable in the Page Header:
<div class="app-bar"><h4>Page Header [Counter {{Counter}}]</h4></div>
The code for the counter components is similar to the app.component.ts file.
The only difference is that they also call the CounterService’s setCount method to set the current count when it is incremented:
import { Component, OnInit, OnDestroy } from '@angular/core';
import { Subscription } from 'rxjs/Subscription';
import { CounterService } from '../services/counter.service';
@Component({
selector: 'counter',
templateUrl: './counter.component.html'
})
export class CounterComponent implements OnInit, OnDestroy {
CounterSubscription: Subscription;
Counter: number;
constructor(private _CounterService: CounterService) { }
ngOnInit() {
// Subscribe to the Counter service
this.CounterSubscription = this._CounterService.getCount().subscribe(
(count: number) => {
this.Counter = count;
});
}
public incrementCounter() {
// Increase the count
this.Counter++;
// Set the new count
// and update any subscribed clients
this._CounterService.setCount(this.Counter);
}
ngOnDestroy(): void {
// Important - Unsubscribe from any subscriptions
this.CounterSubscription.unsubscribe();
}
}
Links
Angular 2-4
Upgrading JavaScriptServices and PrimeNG From Angular 2 to Angular 4+
Create Your Own Angular 4 Application Shell Using PrimeNG
rxjs - Angular 2 - Behavior Subject vs Observable? - Stack Overflow
Angular Components 101 — an Overview
Download
The project is available at http://lightswitchhelpwebsite.com/Downloads.aspx
You must have Visual Studio 2017 (or higher) installed to run the code.
1 comment(s) so far...
Nice article.
For those that prefer it, especially when the callback logic is complex, you can replace the inline callback with a named function.
ngOnInit() { // Subscribe to the Counter service this.CounterSubscription = this._CounterService.getCount(). subscribe ( (count: number) => this.consumer(count) ); this.msgs = []; }
// Callback for this._CounterService.getCount().subscribe consumer(count: number): void { this.Counter = count; }
By Richard Waddell on
5/8/2018 2:53 PM
|