Angular 5 HTTP Form Inputs & RxJS

Angular 5 Form Inputs

Whatever framework you are using, forms are a key component of any website or web application.  They provide us with one of the most important aspects of user interaction. We need to give the user a clear understanding of what information we require, while also validating his/her data in the process.

If we want to provide a real-time interface for the user that reacts to his/her inputs and selections, we can use RxJS Observables and Angular form controls.

This tutorial is based on my application Beer Name Finder which you can view here:

.

The application takes user input, sends off a HTTP request while the user is typing and retrieves a new dataset based on their current search term in real-time.

The user can also change the beer category through a drop down selector in the same way to get a similar user interface update.

The full repository for Beer Name Finder is available here.

I think this is one of the coolest things about modern UI manipulation when combined with modern frontend frameworks. And surprisingly, it is not overly difficult to get running once it is broken down into different segments. I will detail how to go about that in this post.

And if you enjoy this dashboard, please consider giving it an upvote on Product Hunt here.

On a side note, if your looking to expand your Angular and Typescript knowledge I highly recommend this Angular & TypeScript book by Yakov Fain.

So, let’s begin.

Populate an Angular Input

Let’s say we want to populate a select dropdown field from a HTTP call. I used this process for my Beer Application so I’ll be using that as an example.

To start, I retrieved a list of beer categories from the BreweryDB API and applied them to a select dropdown field.

In our search.component.ts I declared the main variable types used:

The FormControl is the most notable declaration here:

It tracks the value and validation status of an individual form control e.g input field.

It is one of the three fundamental building blocks of Angular forms, along with FormGroup and FormArray.

I declared an array of type Beer from an imported TypeScript definition:

This maps our desired beer properties from our HTTP request to a beer object.

My imported type definition for Beer looked like this:

I then initialised my data service (beer.service) in the constructor:

I used a method in _beerService to retrieve the beer categories to populate the select dropdown field.

In my lifecycle hook ngOnInit I then invoke two custom functions:

The first initialization of the dropdown contains this functionality:

I got an initial dataset of beers from our getBeers() function I have covered this function extensively in another post here:

After this, I invoked the getCategories() method from the beerservice file which contains the following functionality:

This is yet another HTTP request similar to all others in the service.

this._baseUrl refers to the BreweryDB API endpoint:

The only unusual thing in the getCategories method is the Array.from(new Set(this.categories))

This could have been done a number of ways to get a new array object from an iterable but I used the Array.from() method here but this is just personal preference.

So now my categories object will now contain data from our request that look something like this:

If we now examine our markup for the form we can see this:

Just concentrating on the select field for the moment:

We can see that the *ngFor directive has iterated through our retrieved categories array. At this point, I navigated and selected a category option.

This next section is possibly the most interesting thing about creating a reactive input in Angular 5. It uses RxJS methods to track data from an input field and allows you to manipulate that data from that input field as an Observable.

We now are going to look at the method listenForInput():

So starting with:

This term value is a reference to our FormControl declared earlier in the file:

The debounce time:

Waits for a new change in the input field from the user every 400 milliseconds. If a change occurs before 400 milliseconds from the previous change it discards those values.

The distinct method:

Ensures that there is a new value in the input field before declaring that theres been a change.

Once this criteria is met, we are finally able to subscribe to the Observable:

From here I have invoked:

This is just another http call to retrieve a list of beers using the parameters term and this.currentCategory which will filter the response to the desired dataset.

I’ll show you this searchTerm method as well:

This seems quite complicated but its actually not doing much more different than any other of our HTTP calls in the service.

We are using the term from our input field in the api request:

We are making sure that the category property exists in the our respoinse:

But most importantly, we are assigning this new information to our beer observable source by using .next().

This beer observable is being subscribed to elsewhere in the application so the UI will automatically get refreshed which is very handy.

And when we have selected a new value currentCat(selectedCategory.value) will be called:

This is just one example of using RxJS and Observables to track  a users interaction with a form element and have the UI refresh accordingly.

On a side note, Observables in general should be used when there is more than one stream of data. This is when they are most effective. But its fun to demonstrate their power in an application such as this.

The full repository for Beer Name Finder is available here.

Angular 5 HTTP using Obvservables – Part 3

WRITTEN BY GARETH DUNNE @JSDIARIES

In this third part of this reactive data series we will be focusing on displaying the data results from our HTTP call in our view component.

While part 1 and 2 felt like setup processes we will now get to see how our data will interact with our view layer.

Again, if your looking to expand your Angular and Typescript knowledge I highly recommend this Angular & TypeScript book by Yakov Fain.

This tutorial series is based on my application Beer Name Finder which you can view here:

.

If you enjoy this dashboard, please consider giving it an upvote on Product Hunt here.

Linking the Component to the HTTP Request

In order for our home.component.ts file to have access to our beer HTTP methods we have to inject our beer.service.ts into it.

Simply import this service along with the required imports for using Rxjs Observable and Subscriptions. These Rxjs imports will be a key factor in making our data reactive.

We will also import our Beer type definition model that will map all the appropriate properties from our data call.

We have our ngOnInit() lifecycle hook that comes as standard when you generate a component through the Angular CLI.

Inside this we then invoke two methods one after another in order to separate our logic for retrieve and displaying the beers. We will include this logic as I explain it.

There are a lot of things going on here so first of all, remember the beerAnnounced$ variable that we created in our service in part 2?

It looked like this:

Well, beerAnnouncedSource is a list of type Beers that are also Subjects. Without getting into the complexities of the Observable pattern think of a Subject as a open channel of data that will announce itself to any of our components that have specifically subscribed to it.

There are plenty of other ways to make reactive component data using Rxjs however using a Subject allows us to produce a hot observable of data. In otherwords, you could say this is a constant stream of data.

On top of this, a Subject inherits the same methods that an Observable and shares similar functionality but a Subject has a state and it keeps a list of observers.

So we have access to the beerAnnouncedSource variable through our beer services. We then invoke .subscribe() on it in order access its data.
We then use ES6 arrow filter functionality => and push the results in to a new local array variable.

We will only get the benefit of having a reactive Subject by having changeable data. You might be asking why is it being used for one API call? Well further down the line we will be using a search functionality where you can type into an input field and the Rxjs variable will get refresh as you are typing. This gives a feeling of a live auto populating search.

Reso

We can now import our Beer class to any of our components to reference data retrieved from the Beer API. So our home.component.ts file should look like this:

In the getBeers() method we show our ngspinner which is detailed in the next section below.

We call our get beers method from the beer service:

We publish this to data so that it can become a ConnectableObservable:

This means that its only a reference to the source data.

We need to subscribe to the data and map it to the local array that was initialised at the start of the file of type Beer

And possibly the most important thing to note here is the this line:

This allows our hot variable to received data emitted from the Observable is was only previously just referencing.

While I admit the whole Rxjs Observable pattern can be complicated to wrap your head around initially. When its broken down into the idea that publisher send data and subscribers receive it. Everything else in between can be thought of as methods that tweak the way that data is emitted and who receives it.

So with all this data readily available we just have to map it to our UI.

Mapping Data to UI

In our home.component.html file we need iterate through the beer data and apply it to our user interface.

So we are just using some Angular directives to create markup from the beer data.

We check if our beer array exists:

UI Loading

Having an indicator for loading is optional but provides a nice bit of user experience as your HTTP is working itself out. I have found a nice little library that will display a spinner for all your HTTP requests. Check it out here. In your app.component.html file insert the element that references the loader like so:

And in your service you need to import :

and replace all instances of Http with HttpInterceptorService

A loader nicely styled loader will appear whenever making a HTTP call from anywhere in your app.

SEO