4 Useful Reactive Programming Implementation Styles
4 Useful Reactive Programming Implementation Styles
Build web applications using RxJS with Angular.
Source: Pixabay
This post is a follow-up to my previouspost about RxJS Operators. I’m going to jump right through the practical examples of using Reactive programming in building web applications.
All my code samples are using RxJS with Angular written in TypeScript. Every section will start with a GIF of the final result.
Events From Button Clicks
I’m kicking us off with a simple example. We have a button that triggers an event when it is clicked — an everyday use case in web development.
Button click example by the author.
The button that emits events will be treated as an Observable with a stream of events. Let’s take a button that prints to the browser console when it is clicked.
<button id="mybutton">Click me</button>
We will first initialize an observable from that button that we can subscribe to for click events.
const observableButton: rxjs.Observable = rxjs.fromEvent(document, 'click');
Subscribe a function to the observable that we initialized. That function should print to the web console.
observableButton.subscribe(e => {console.log(e.type)});
Code sample by the author.
Events From Text Input Changes
Let’s use a search input field as an example. We are typing a text on an input field. Every change in the text emits an event. Our frontend code will then call a Search API whenever appropriate and not on every emitted change event.
Input change screencast by the author.
Let’s start with our HTML input tag that will accept the search text input.
<input type="text" [(ngModel)]="data" (ngModelChange)="inputChanged($event)" placeholder="Search" name="data">
Every change in our search text will trigger theinputChanged()
method.
Let’s then initialize our search subject observer as an (appropriately named)RxJS Subject.
searchSubject$ = new Subject<string>();
OurinputChanged()
method will print to the web console and send the event object to our search subject observer.
inputChanged($event) { console.log("input changed: ", $event); this.searchSubject$.next($event); }
We will usedebounceTime
in our observer to not trigger our API call function every time there’s a change in our input text. Our API call function gets invoked after a stream of input events has stopped within a specified time.
ngOnInit() { this.searchSubject$ .pipe(debounceTime(200)) // replace this with a search API call .subscribe(x => console.log("call search API: ", x));}
Play around with the code sample in StackBlitz. Try to removedebounceTime
and observe how it behaves.
Code sample by the author.
REST API Requests
Let’s extend our previous “Events from text input changes” example by querying the Reddit Search API. Our sample page will then display the meme images retrieved from the API.
Screencast by the author.
We are extending the HTML code by adding a Clear button for convenience. This button clears the input text.
<input type="text" [(ngModel)]="searchString" (ngModelChange)="inputChanged($event)" placeholder="Search" name="searchString"/><button (click)="searchString = ''">Clear</button>
Since we will now be dealing with an API request, let’s use Angular’s HTTPClient.
import { HttpClient } from '@angular/common/http';
And wire up our method that will call the Reddit API.
queryAPI(searchString) { return this.http .get(`https://www.reddit.com/r/memes/search.json?q=${searchString}`) .pipe(map(result => result['data']['children']));}
Since we will now display search results on the page, let’s initialize the results Observable.
results$: Observable<any>;
We are currently using two new operators in oursearchSubject
.distinctUntilChanged()
ensures that we will only fire an event when there is a change in our search subject. WhileswitchMap()
will “switch” to a new observable — which is thequeryAPI
method. I’ve also covered switchMap with sample code in my previouspost about reactive programming.
ngOnInit() { this.results$ = this.searchSubject$.pipe( debounceTime(200), distinctUntilChanged(), switchMap(searchString => this.queryAPI(searchString)) );}
Now that we have the results Observable set let’s use it in our HTML code to display our API search result. We are iterating through the response of our API call and displaying the image for each result element.
<div *ngFor="let result of results$ | async"> <div *ngIf="result.data.thumbnail != 'default' && result.data.thumbnail != 'self'" > <a [href]="result.data.url"> <img [src]="result.data.thumbnail" alt="" /> </a> </div></div>
You can find the complete code below in StackBlitz.
Code sample by the author.
Mobile responsive website layouts
Another excellent application of observables is for implementing mobile responsiveness in your web application. For example, our website displays two vertical columns for desktop view and two horizontal rows for mobile view.
Screencast by the author.
Let’s start with an observable for window size changes.
resizeObservable$: Observable<Event>;
Using RxJS’sfromEvent
, we can listen to window resize events.
this.resizeObservable$ = fromEvent(window, 'resize');
Now that we have a resize Observable let’s subscribe to it. Once we are subscribed to the window resize stream of events, we now have access to the window’s size for every resize event. We will change our website’s layout based on the current window size during a window resize event.
ngOnInit() { this.resizeObservable$ = fromEvent(window, 'resize'); this.resizeSubscription$ = this.resizeObservable$.subscribe(e => { if (window.innerWidth <= 400) { this.renderMobileView(); } else { this.renderDesktopView(); } });}
Our render mobile and desktop methods will change the boolean value ofmobileView
.
renderMobileView() { console.log('render mobile view'); this.mobileView = true; }
renderDesktopView() { console.log('render desktop view'); this.mobileView = false;}
Using themobileView
boolean, we can change the CSS class of our HTML element. Changing the CSS class means that we can easily switch between mobile and desktop views.
<div class="container" [ngClass]="{ 'mobile': mobileView, 'desktop': !mobileView}"> <div class="col1">col1</div> <div class="col2">col2</div></div>
The complete sample code is available in StackBlitz.
Code sample by the author.
I hope that you find this helpful and you can apply it in building your next web application!
If you like this post, you might also like: