Understanding RESTful APIs
Mastering the basics of Angular's HTTP module will open up the door to interact with thousands of exciting web-based APIs. By the end of this lesson, you'll have the basic tools you would need to do things like request weather data, stock quotes, nutrition facts, as well as interact with major platforms like Facebook, Twitter, and Amazon Web Services.
The one thing these products all have in common is that they provide a RESTful API that you can consume from your Angular app. Before we jump into the code, let's quickly look at what a RESTful API is and how communication works between the client and the server. So here we have a client on the left and a server on the right. REST is simply a way for these two parties to communicate in a standardized way.
When the client makes a request, it's going to use a specific verb or method to interact with the server. First, we'll go ahead and make a GET request. This tells the server that we only want to retrieve data and we're not going to modify it in any way. The server will respond with the status code as well as the data that was requested. If it was a successful request, it should be a 200-level response. But if the request wasn't valid, it should be a 400 or 500-level error response. A 400 response generally means the client screwed something up, and a 500-level response generally means there was an error on the server itself.
If we send a POST request, we're telling the server that we intend to create new data. When you send a POST request, you also send that data payload with it, which is the data you intend to save on the server. After the server successfully saves it, it should respond with a 201 success message this time, saying that the resource was created.
In addition to GET and POST, you also have other verbs such as PUT, PATCH, and DELETE. They all work in a similar way, just conveying a slightly different message for what you intend to do on the server. And that's basically the gist of how REST works from a very high level.
Making a Basic GET Request
Now let's start retrieving data from a RESTful endpoint using Angular. For this lesson, I'm going to be working from a StackBlitz project. This allows me to include a link in the description where you can run this code and fork it for yourself.
The first thing we're going to do is go into the app.module and import the HttpClientModule from angular/common. Ever since Angular 4.3, we've had a client module built into common, so just make sure that's the one you're actually using. From there, we can go into the app component and import the HttpClient, which works just like an Angular service. It's injectable, so we can just add it right in the constructor.
Then I'm going to define a rootURL variable that represents the main HTTP endpoint that we're going to be using. For this demo, I'm using JSONPlaceholder, which is just a mock API that we can send requests to and receive responses from. So we'll just go ahead and copy and paste the URL, and then we'll do the rest of the work in Angular.
So first, I'm going to opt out of TypeScript's static typing and we're going to make a GET request to the API. First I define a getPosts method, and then I'll define the posts variable by calling http.get, and that's going to return an observable. So we'll pass in the rootURL, and that should return an observable of the response from the API.
In the HTML, the first thing I'll do is set up a button that will trigger the API call. And then from there, I'm going to use ngIf to loop over the observable and unwrap it with the async pipe. Then I print it as a JSON object, but you could do anything you want here with the underlying data. Now if we load the actual app in StackBlitz, we should see the response from JSONPlaceholder. So after clicking the post button, we get a response of an array of different post objects.
Adding Strong Typing with Interfaces
For this first example, I opted out of TypeScript, but now I'm going to show you how to use your own interface and pass it down to the get method. So we're exporting an interface called Post and it's just going to have a couple of properties here for an ID, user ID, title, and body. Now we can import it back in the app component, and we'll also import the RxJS Observable.
Then we'll apply these to the posts variable. So we're going to say our posts variable is an Observable that contains an array of Post objects that adhere to the Post interface. The return value on http.get is typed as an object, so we need to change that to our Post array. So if we go ahead and run this code, we get the exact same result, but we have the benefit of strong typing in our code at this point.
Sending Dynamic URL Parameters
So now I'll go ahead and opt back out of TypeScript to show you how to send URL parameters with your requests. It's really common to send a parameter with the request to limit it or filter it in some kind of way on the server. With JSONPlaceholder, we can filter posts by the user ID. So this is how we would do it if we were going to hard-code the parameter: we'd have a question mark followed by the parameter and equals some value. This works fine, but it's not a very maintainable way to go because if we have multiple parameters or if they get created dynamically, it's going to be hard to hard-code them directly in a string.
What we can do instead is use Angular's HttpParams class to build these parameters dynamically. We do that by instantiating a new instance of the class, and then we can call set or append on the parameter and the value that we want to set. And then we pass that as an object as the second argument to our get request. When we send this parameter, JSONPlaceholder will only return the posts that have this matching user ID.
We can follow a very similar process for HTTP headers, which is going to be a very common use case if you're using authentication in your app. Let's imagine that we want to send a request that can only be performed by that currently logged-in user. In that case, we could hypothetically send a JSON Web Token with their authentication details in the header. Then the server could decode that token to validate that this user does have the right permission to make this request.
So just like before, we pass the headers as the second argument in the get request. So now I'm going to test this out by going to the Network tab in Chrome. We can inspect the request in the Headers tab, and we can see here that it has the authorization token that we had defined in Angular.
Creating Data with POST Requests
So now let's go ahead and send a POST request where we actually modify data on the server. So we'll create a new variable called newPost and also create a new method to handle this operation. post is almost identical to get; the only difference is we send a body with the request that represents the data that we want to modify on the server. So we'll go ahead and create some random post data here, and then we'll send this object as the second argument to the post request.
So we call http.post to the same URL and pass it the data payload. In the HTML we'll create another button that triggers that createPost method. The newPost variable is just a single object observable, so we can get that data by calling async and json. Then we can load the app, and if we click Create Post, you see we get back here the object itself with that new data that was created on the server.
One of the most powerful features about Angular's HTTP client is that you can use any RxJS operator on it. So let's say we want to map the post down to just the title. We can just throw in the map operator and then map the post down to just its title. So if we rerun the same method, we get just the title back instead of the full object. As you can imagine, there's all kinds of clever things you can do with RxJS to handle multiple requests and map everything down to the exact data format that you want.
Advanced Error Handling with RxJS
You can also use RxJS to handle errors. So in this case, we'll import the catch and retry operators, and also the of operator from Observable. Then I'm going to make the POST request on an endpoint that doesn't actually exist, which is going to trigger an error response.
First, I'm going to tell RxJS to retry the request three times if it fails. And if it continues to fail, we'll go ahead and catch it, and we'll console.log it as well as return it back as an observable. I'm doing this just to show you the response on the front end, and we can do that by returning an observable of the error itself. So if we try this out, we can see we get four POST requests here: the original one plus the three retries. And when it fails for good, it console logs the error and displays the error object in the user-facing front end.
Bonus: Auto-Generating Clients with Swagger
So that covers the basic HTTP concepts that you need to know to get started using third-party APIs in Angular. But there is one really cool tool I want to show you before the end of this video called Swagger. It's a framework for building APIs both server-side and client-side. It allows you to define API code in a readable YAML format, and it can actually automatically generate a lot of your Angular client-side code.
So you would define the details of your API here on the left, and then it gives you a readable, documented format of it on the right. Then if you go up to Generate Client and go to TypeScript-Angular 2, it will generate an entire Angular app with the Swagger API built into it. You can download the generated code and then open it in your editor, and you'll see you have a bunch of Angular code here with the HTTP module. But I should warn you, this is the previous version of HTTP in Angular, so just keep that in mind. Many of the methods and concepts will be identical, but you won't be able to use this code line for line. In any case, it should give you some good ideas and help you jump-start the process of building your own front-end API client.
That's it for Angular HTTP. If this video helped you, please like and subscribe. And if you want to go beyond the basics, consider becoming a Pro subscriber at angularfirebase.com. You'll get a free copy of my book as well as one-on-one project consulting. Thanks for watching, and I'll see you next time.