⚠️ This lesson is retired and might contain outdated information.

Load Data Based on Angular Route Params

John Lindquist
InstructorJohn Lindquist
Share this video with your friends

Social Share Links

Send Tweet
Published 8 years ago
Updated a month ago

You can load resource based on the url using the a combination of ActivatedRoute and Angular’s Http service. Since the params and Http are both streams, you can use RxJS to get the data off the param then switchMap over to an Http request using that data.

[00:00] Now it's boring just to see contact four in there. Contact four is Darth Vader, and we ought to see Darth Vader. Let's hop over to our contact component for the individual contact. Instead of just ID here, we can actually say contact, and make this contact. We'll make this contact.

[00:21] This isn't just going to be RouteParams map. We're going to map to the ID. Then we're going to do what's called a switch map, where we take that ID and we pass that along to the HTTP GET. In the constructor I'll need to inject the HTTP service.

[00:40] I'll need to make sure and import this switch map method. Just duplicate that, and this one's switch map. Then we can HTTP GET. I'll grab the URL from contacts component, this whole thing here, back to my contact component, and the string of this plus the ID. That's coming from here.

[01:04] We're getting the ID from the route and then passing it along to the next operator in the chain and taking that ID and switching over to a different stream. This stream is the HTTP GET. Now, as always, we do need to map the response and parse the JSON on it, but after that we're done and we have the entire contact object.

[01:28] I'm going to wrap this contact async in some parens. I'm going to do this syntax, ready, question mark, dot name. I'll show it working first and explain it. I'll click on Darth. It looks like this failed because of a missing /. This needs to be /ID here. I'll hit save and try it one more time.

[01:54] Now it will say contact Darth Vader. You might have noticed how this loaded just a little bit after the page loaded. What's going on here, and what this syntax is doing, if I delete this question mark, and you look at what happens in the console, it says that name is null.

[02:13] That's because we're trying to access this before my HTTP has loaded. One solution is a null guard where you put the question mark in there and say, "Hey, don't load this if this is null." Another one is, that I prefer, there's an operator called start with.

[02:30] I can actually start with an object that has the name of, we'll just say loading, just to show this happening. I'll hit save. Once I click on contacts, and then Darth Vader, there's a brief loading before it turned into Darth Vader.

[02:48] This is never null, it's actually starting with an object with a name of loading, so you don't have to guard against it being null. Even if you just make this blank, it will start with a blank name, and you'll avoid that null check. As soon as this loads, the Darth Vader name will appear.

[03:06] Let's finish this off by wrapping this in an H2 to make it nice and big, and then loading the image of Darth Vader beneath it. The image is also on this contact object, so if I grab this and paste it here, and say dot image, let's also do a start with image of nothing.

[03:30] You'll see that the image is Darth Vader.jpg, but we need this to link to our API here/Darth Vader.jpg. Let's pull this out and bring this up here. Say it's an API. This can be API plus people/ plus ID. After this line, when we have our object back, I want to map again where I have my contact.

[04:02] I'm going to object assign. This is where I can create a new object, pass in my contact, and then override what the image is. I'm going to say the image is API plus contact.image. This way our contact has now become this new object.

[04:23] Object assign takes everything from contact and assigns it to this empty object. Finally we get the contact image, which by default was just contact image, or the Darth Vader underscore jpg. Now we're making it so it's the entire API/Darth Vader jpg.

[04:42] Now when I hit save, you'll see that here is the entire URL to that image. We can now take this entire URL to the image. I'll cut it out of here. I'll evaluate the right side of this, using these square brackets. I'll paste this in. It looks like I didn't copy a paren.

[05:00] Now when I hit save, we'll have Darth Vader and the image underneath it, and I can navigate back and forth between my contacts, Han Solo, Yoda, and I'll get their name and the image from this API.

Julia Passynkova
Julia Passynkova
~ 8 years ago

The observable contact$ is used in two times with async pipe (two subscription) and therefore two remote calls are executed.

John Lindquist
John Lindquistinstructor
~ 8 years ago

Yeah, I should expound on that with a follow-up.

Christopher Kwiatkowski
Christopher Kwiatkowski
~ 8 years ago

I would like to know what are the best practices with regard to resolving data when using the Angular2 Router.

I typically work in systems where security is paramount to performance and I would typically block the route change if the authenticated user was not authorized to access a specific record e.g. a Contact.

So, I would lean toward creating a DetailResolveService that implements Resolve<IUser> (imported from @angular/router) and then configure that DetailResolveService in the mymodule.routes.ts file to be resolved prior to the route change to display the Detail of a single record e.g. a single Contact record.

Your tutorial shows illustrates the use of pulling the Contact's ID off of the route params in the constructor and then beginning the resolve process for the Contact data based on that ID.

I have also seen plenty of examples of developers resolving data within the ngOnInit() method by implementing the ngOnInit "interface?" / lifecycle hook.

What is your best practice recommendation for those of us looking for the best way to resolve data in a DRY manner.

Should we encapsulate the resolving of an Observable HTTP call in the constructor prior to ngOnInit()? Should we encapsulate the resolving of an Observable HTTP call in an ngOnInit()? Should we encapsulate the resolving of an Observable HTTP call in a ResolveService that is configured to be called by the angular router prior to a route change and then assign the resolved data off of the this.activatedRoute.data?

Michal
Michal
~ 8 years ago

Why "loading..." phrase is that long time when app is so small ? Is not a problem when you are working with much more bigger application ?

John  Lorrey
John Lorrey
~ 7 years ago

First what is the plugin you are using in Webstorm to dynamically add the libraries based on use in the code? Thats rad. Second stop using that plugin in tutorial videos. Its so freaking hard to follow along with you as you code literally autogenerates as you talk and in you never see any keystrokes to notify you where that is. I am pretty fast coder who is a native English speaker i can not even imagine someone else trying to follow it. i had to download the videos just so i could rewind enough to see where you getting the code inserted. Its WAY WAY to fast. I have never said that to anyone before I watch most people's video at 2x speed but you man take the cake for talking fast while not even coding what your stating. The thing that did for me in this video is that your like ill include http in the constructor but you can't even see it in the video the visible constructor param. its just 'htt'. I was like ok this is enough. Third and this is a must. Stop using bin to host your code. When i download it i can't run it on my box making your stuff almost un-usable. I signed up for your service to help me be faster at getting the concepts. I have had to spend almost 4 hours trying to decode your code to try understand what you are doing. We all get your good but please head my advice.

Markdown supported.
Become a member to join the discussionEnroll Today