How to Render API Data in an Angular 2 Application
In this screencast you're learn how to render API data from a Rails microservice into an Angular 2 application.
Guide Tasks
  • Read Tutorial
  • Watch Guide Video
Video locked
This video is viewable to users with a Bottega Bootcamp license

So this guide is going to be the moment of truth. This is where we are going to connect our angular application and wire it up directly so that it will show our documents here on the screen. So the very first thing we need to do is because we're in our component we need to pull in the Http library inside of our app/styles/app.module.ts. So come up here and you can put it anywhere I'm going to put it right under the FormsModule and we want to bring in Http. And this is going to be from '@angular/http'.

large

And then we need to put it inside of our imports. So here it's just going to be a comma and then HttpModule.

medium

Then hit save everything's still going to be working because we haven't actually changed anything. So now coming up to app/documents/documents.component.ts. This is where all of the changing is going to take place. The first thing we need to do is we need to create an OnInit call so I'm going to pull in OnInit

large

and remember whenever we import OnInit then we also usually want to implement it. So I'm going to implement OnInit which is going to tell typescript that we need to have an OnInit function so I'm going to get rid of all of our document's data and delete all of it. And instead, I'm going to leave documents just as an empty declaration so I'm going to have

documents: Document[];

What I'm saying with this is that documents is going to be a variable and it's going to have the document data type established for it. Now the next thing we're going to do is call a mode.

documents: Document[];
mode = "Observable";

So this mode is going to equal observable and that's just going to let the documents component know. This is an observable. Later versions of angular may or may not have this as a requirement. But for right now this is what I had when I initially built out the application.

So next thing to do is to create a constructor, our constructor is going to be very similar to the other constructor we built. Except this time instead of importing Http our constructor is going to use dependency injection to import our document service. So we are going to pull in documentService and set it equal to DocumentService.

large

And that's all we need to do on that side besides just set up our empty implementation. Now we have a complaint from typescript here because we haven't imported it. So let's come over here and we're going to pull in our DocumentService from './document.service'.

large

I save this than that complaint goes away and we are good to go. Now obviously we don't have any documents here because I got rid of all of our fake data and that's fine. Next thing is we're going to take care of this little complaint because we said we would implement OnInit. We're lying right now because we haven't implemented it yet. So I'm going to say

ngOnInit() {

}

It's going to take no arguments and inside of the function. This is where we're actually going to make our get documents call. So I'm going to it leave empty for right now.

And now let's go and create our getDocuments function. Now the first question you may ask is why are we creating a getDocuments function when we already created one here in our service and that is a great question. The reason is because we want this service to be as generic as possible because there are times where we may want getDocuments to be called from some other kind of component so we may want the home page to have documents because we may want to put the top two documents on the home page. But if we limit it to two, so say we run a query and we limit it to two inside of our service then that's also going to limit it to two everywhere else it's called. So this should be as generic as possible and it is all we're doing is we're connecting to the API. And from there we're mapping the response to JSON and handling errors.

Now, what the component is supposed to do it's going to have a getDocuments function that's going to be specific to how we want the data in the component. So it's all about just having the data available in the way that the component needs it. So I'm going to create a function and it's going to be called getDocuments. It's going to take no arguments.

getDocuments() {

}

And now inside of this, we're going to call our documents service. So this is by using dependency injection as we now have access to it.
So you say

getDocuments() {
  this.documentService.getDocuments()
}

I'm going to go down a line and hit tab just so we can line this up. But essentially what I'm doing is I'm chaining another function onto this so this all could be on one line with dots. But the common convention you'll see in angular circles is putting them on multiple lines just so they're easier to read. So I'm going to to chain a very powerful function called subscribe

getDocuments() {
  this.documentService.getDocuments()
        .subscribe

Subscribe is something you're going to be seeing all the time in working with observables and what it is, if you remember back to when we talked about observables and I showed you that diagram of the way that the streams work subscribe is what is communicating directly with that stream process. So whether it's at the beginning in the middle wherever it is subscribed is what's actually making the call. So here with subscribe I am going to give us some room because we're going to pass subscribe in a couple arguments and the first one is going to be a function. So subscribe is actually going to take two functions inside of it and we're going to pass an anonymous function by using the fat arrow syntax and say

getDocuments() {
  this.documentService.getDocuments()
        .subscribe(
          documents => this.documents = documents
        )

So what this is saying is take in this.documents, which is going to start out as an empty array of documents. And we're saying take this and set it equal to documents. And if that makes no sense to you don't worry at all. That's perfectly fine. We're going to go through it in a second. So error is going to be mapped to this.errorMessage and this is going to be equal to <any>error

getDocuments() {
  this.documentService.getDocuments()
        .subscribe(
          documents => this.documents = documents
          error => this.errorMessage = <any>error
        )

If you're wondering where our error message is that's a great question that is something we need to create. So here that's why you're getting a complaint or it says property error message does not exist on type documents component. So just come right over here and right underneath documents will say errorMessage and we'll say it's of type string;

large

and that fixes it. So this should be the initial parts of what we need for getDocuments. So let let me take a step back and walk through what's happening here. So subscribe takes two functions as arguments if you remember back if you went through the typescript course then you know that you can create a function that takes functions as arguments. And in this case, subscribe takes two of them one it takes for success message which is right here

large

and the other one it takes for the error message and which is the second one.

large

And you know they're function arguments because we have a comma in between them and they're inside of parentheses. So this first function is going to say documents and then what this is going to do is because we're using an anonymous function it's going to instantly convert this documents

large

which is our array right here to documents.

large

And if you're wondering what in the world this is or where it's coming from. It's from our documentService. So this is all it's doing is it's calling our DocumentService ( in app/documents/document.service.ts ) and it's calling our getDocuments() function. Remember when I said this

large

is doing all the magic here all we're doing is we're creating the call to that, so get documents is not calling the function inside of getDocuments() it's actually calling the function from documentService and you know that because it's chained to it just like this documentService.getDocument().

So that is the way our getDocuments works, all it's doing is it's creating a connection to our service and then it's calling subscribe() on it. And that's a requirement from Observable from the Observable library. Which reminds me we need to import the observable library right underneath here. I'm going to pull in Observable and I'm going to pull it in from 'rxjs/Rx, so like this.

large

And now that is going to be made available to us. And so we have still a few other changes we have to make before this part is going to start working. So the first thing is we need to make a provider. Now you know that in app.module.ts we created a provider here for our document service but we also actually have to do this inside of our documents.component.ts. So inside of our documents.component.ts here I'm going to place this. I'm going to give a comma and then put providers. I'm only going to do one provider so we can put this on one line. And so our document service here is going to be a provider and this is a requirement because the component needs to know what is providing the data. And that's what this is going to do for us right here.

large

So we have our provider and we have our service. Everything so far is set up pretty close to being right but it's still not going to show anything here (in the browser). And the reason is because our ngOnInit() is blank. So this is the last part. This is the big one. So now that we've set all this up we've set up our service which is connecting to the API. We've set up our module our app.module.ts so it can connect to outside services with Http. We've done all of that. And now ngOnInit() is simply going to call getDocuments. But I want to do something kind of cool here and this is where we are going to be able to use observable and I'm going to say

ngOnInit() {
  let timer = Observable.timer(0, 5000);
}

The Observable.timer() is a function provided by Observable and what it's going to do is it's going to let us dynamically check for data changes. So this is essentially like setting up almost like a watcher where I can set up things and it's going to take two arguments the first one is going to be 0 and the next is 5000. Now if you are wondering what in the world that's doing if you have sublime text it gives you some hints. So timer creates an observable that starts emitting after an initial delay and emits ever increasing numbers after each period of time thereafter. So essentially what this is going to do is we set up a timer. The 0 means I want you whatever I pass this to I want it to start right away. If we wanted this to start in two seconds. So in other words, if we wanted the page to load and then wait two seconds to make the API call then I could do 2000 because this is 2000 milliseconds which equals two seconds. But I want it to start right away because I want the pages to load fast and then 5000. This is how many seconds we want in between calls. So here I want to check on the document API. I want you to make a call to that every five seconds. So what this is going to do is it's going to allow us to make calls in the background so say that we have a freelancer who's on the document page and then a new document gets added to the database without even hitting a page refresh a new document will be added. That's really cool. I love the way that this was implemented in angular and specifically this is part of the rxjs library.

So now what we have to do is use our timer and then we're going to use subscribe again and remember subscribe is just something that is used whenever we're working with observables and we want them to start. So subscribe if you remember also is going to take a function as an argument. And this one is going to be a function that we want to be run right away. So if you remember back to your typescript learning by putting in the double brackets followed by the fat arrow. This is going to be an instantaneous function and so we'll say this.getsDocuments().

ngOnInit() {
  let timer = Observable.timer(0, 5000);
  timer.subscribe(() => this.getDocuments())
}

And that should be it. I do not see any errors here. So this is going to be the moment of truth when I hit save. And let's see what happens on the browser and look at that this is data coming in from our Rail's API. So here we have all of the data that is coming in from the JSON feed. So from our other application it's coming in and it's populating our view. And you notice how this worked how we even were able to do this without making a single change to our view code if you can do that that's a sign that you are building your application the right way because we don't want our view to care where it's getting the data from. All we want it to care about is the structure and to have the parameters directly communicating with the component that we already set up. So here we have all of these calls working properly ( in app/documents/documents.component.ts ) and everything in the browser is just perfect. I'm very excited about it. If you followed along and it's working for you now congratulations you've created your first direct connection between microservice applications and that is something that you should definitely be proud of, in the next guide I'm going to show you how we can play with the observable that we implemented and show how we can make some real-time updates and how we can also change the rails application and have it make changes with how the data is viewed on the screen.

Resources