In this section, we're going to look at implementing routing and navigation. So by the end of this section, you will have an in-depth understanding of how routing works in Angular, and you'll be able to add navigation to your Angular apps. More specifically, you're going to learn about configuring routes, implementing single-page applications, working with route and query parameters, and programmatic navigation.
Now let's get started. So far you have seen a few of the built-in modules in Angular. We have used the forms module, the reactive forms module, the HTTP module, and now it's time to explore another module. That is the router module. So in this module, we have a bunch of directives and services that we use for implementing navigation in our applications.
You're going to learn about this module throughout this section. Now there are three steps to implement navigation. First, we need to configure the route in our application.
Each route determines what component should be visible when the user navigates to a certain URL. So a route is the mapping of a path to a component. Second, we need to add a router outlet. And that is where we display the corresponding component when a given route becomes active. And finally, we need to add links.
So over the next few lectures, we're going to explore each of these steps in detail. So here's a simple application we're going to work on throughout this section. On the top we have a navigation bar with two links followers and posts the followers page is what we had as an Exercise in the section about consuming HTTP services. So note the URL in the browser's address bar That is slash followers when we click on a follower We go to a different URL that is profile Slash and here we have two parameters The first one is the username and the second one is the user ID And after that we have a query string.
So we have a question mark with one query string parameter, which is foo. So you're going to learn how to implement routes with multiple parameters and query strings in this section. Now we also have another link on our navigation bar, that is posts, which takes us to our posts page.
And note that the URL is slash posts. So the first step to implement this navigation is to configure our routes. Now back in the project, I'm going to go to app module and configure our routes.
Now if you want to code along with me, download the zip file I have attached to this lecture. Then run npm install to install all the node packages and then ng serve. Okay? Alright, now let's go to app.module.
So the first thing I wanted to note here. Is that in the declarations array you're going to see a few new components So we've got navbar component, which is a very simple bootstrap navigation component. Let me show you so navbar HTML Very simple markup that I copied from bootstrap website.
So on this navigation bar, we have two links Followers and posts now back in app module The other components here are home component, GitHub profile component, and not found component. These are really basic components, there is no code, there is no markup, I simply generated these with Angular CLI for the purpose of this section. Now one more thing I want you to pay attention to is that here we have an import statement to import the router module from Angular slash router. So we have imported our router module, now we are ready to define our routes. So let's go to the imports array right here.
We are going to call router module dot for root. For root is a static method defined in the router module class. And we use this to define the root routes for our application.
now as our application grows we may want to break that application into smaller more manageable modules then in each module we're going to have a set of routes for that particular area of the application then instead of using for root we're going to use for child you're going to see this later in the course so for now don't worry about it so back to for root here we pass an array of routes each route is an object with two properties One is path, and the other is component. With this, we're telling Angular Router that whenever the browser address changes to this path, display this component. So here I'm going to add the first route for our home page.
So the component should be home component. And note that here we don't have a leading slash. So none of our routes start with a slash. And an empty path represents the home page or the default route.
Now, let's add a comma here and duplicate this. the second route is for our followers page so followers and the component is followers it help followers component let's duplicate this again now when we click on a follower we want to see their profile so here for the third route the path should be something like this profile now here we want to add a parameter so slash and to add a parameter we use colon and then we add the name of the parameter so username so in this pass we have a parameter called username that will be placed dynamically at runtime you're going to see this later in this section now the component should be github profile component okay now we can reformat this code it's cleaner easier to the eyes Alright, this is much better. Now two more routes. So let me duplicate this last route. I'm going to change the path to posts and the component to posts component.
Now if the user navigates to a different URL that is not a valid route, we want to display a typical not found page. So let's duplicate this one more time. now for the path I'm going to use two asterisks this represents a wild card and this basically catches any URLs in the browser address bar so here I'm going to change the component to not found component now the order of this route is important So if I put this last route at the beginning of our routes array, this pattern, this wildcard is going to catch any routes. And we're only going to see the not found page. As another example, let's change the path for this route to followers slash username.
So now with this configuration, when we navigate to followers slash anything, the path in the first route here will match the URL, and as a result, GitHub followers component will be displayed. In other words, with this configuration, we will not be able to look at the profile of a given follower. So we need to put the more specific routes on the top. So I'm going to move this on top of the followers route, so cut from here and paste it here.
So now the first route is more specific, and if you have a URL with this pattern, this route will be active and GitHub profile component will be displayed. So this is how we define routes. Next we're going to look at router outlet. So we have defined our routes here in app module.
Now if we switch over to the browser, we're going to see an error. So our generic error handler just kicked in and displayed this alert. Now let's take a look at the console.
So we have this error. Cannot find primary outlet to load home component. So as I told you before, the second step to implement routing is to add a router outlet.
And that's where Angular router is going to display the component that is associated with the current route. So let's go to app.html, so currently we only have the navigation bar, now below that I'm going to add a router outlet element. This is a directive that is defined in the router module.
When Angular sees this, it's going to render the component associated with the current route after this router outlet. So it's not going to render it inside this element. Let me show you.
So back in the browser, all right we don't currently have any errors let's inspect this page so body we have a fruit we have our nav bar here's our router outlet and this is our home component so you can see that it's not rendered inside router outfit it's rendered after this element all right now back to the page let's test our routes So currently we are at localhost port 4200. and as you can see our home component is visible now if I change this URL to slash followers we get the list of followers beautiful so this route is working properly if I change this to followers slash one we get the profile page perfect so our more specific route is working now if I change this to posts We get our posts page, beautiful. And finally if I change this to an invalid URL, we get the not found page. So all the routes are working properly. Next we need to add links. So as we click on these links in the navigation bar we get the right page.
Currently this is not working properly. Now we're ready to add links. So let's go to navbar.html.
So currently we have two links on the navigation bar, followers and posts. And each of these links as you can see has an href attribute. In angular applications we don't use this attribute. Let me show you why. So I'm going to change the value of this href attribute to slash followers.
And similarly for the second link I'm going to change this to slash posts. Let's see what happens when we use the href attribute. So back in the browser, so currently we are on the homepage, but you can see the followers link in the navigation bar is highlighted. I know this is a little bit confusing, don't worry about that, as we're going to fix this in the next lecture.
But note that when I click on the links in the navigation bar, the page is going to flicker. So I click on followers, Did you see the page flickered? It went blank for a split second.
You're going to see this again. So I'm going to click on posts, look. Now this was too fast, you probably didn't see it. Let me click on followers one more time. With this kind of navigation, every time we click on a link, the entire page is downloaded and the angular app is reinitialized.
That's why the page goes blank for just a split second. Now as your application grows, as you have more code, the cost of startup is going to be higher. So that delay will be even more. Now if you look at the browser network tab, so every time we click on any of these links here, all the resources in our application are re-downloaded.
So as an example, you can see all our JavaScript bundles are re-downloaded every time we click on a link. This is something we want to avoid at all costs. Otherwise, there is no point using Angular to build modern applications. When we click on a link, we want only the content for the new page to be downloaded, not the entire application, not all the resources.
So to fix this problem, instead of the href attribute, we're going to use a directive called router link. So, I'm going to replace this with router link. and similarly here, router link, this directive is also defined in the router module.
Now let's go back to the browser, here first I'm going to refresh the page, now open up the network tab, these are all the resources that are downloaded the first time we open the application. Now I'm going to clear all the items in this list, okay, now let's see what happens when we click on any of the links in the navigation bar. so I'm gonna click followers first of all we didn't have a flickering effect the navigation bar stayed there the page didn't go blank only the content area was reloaded now let's go back to the network tab one more time here you can only see the request for the content of the followers page so these are the images of my followers in this list you are not going to see any JavaScript bundles redownloaded and you can verify this by filtering for JavaScript files. Look, there is no JavaScript files. There is no CSS files.
All of these resources were downloaded only the first time. So we refer to applications built this way as single page applications. So essentially a single page is downloaded from the server, and as the user navigates from one page to another, only the content of the target page is downloaded. So single page applications or SPAs. now before we finish this lecture let's go to our followers page and add a link for each follower so followers that HTML so here we have a link for each follower I'm going to replace this href with router link however this time we're dealing with a dynamic url so we don't want to send the user to a page like followers slash one this parameter should be rendered dynamically when we are dealing with route parameters instead of using the router link as an attribute we should use the property binding syntax so property binding and here instead of binding this to a string we should bind it to an expression in this expression we have an array, the first element in this array is the path, so that is slash followers, after this first element we add all the route parameters, so currently we have only one route parameter so we can add that here, follower.login if you want to render the username or follower.id, it doesn't make a difference here, so save, back in the browser now here if I click the first follower, we get to the profile page, and note the URL in the browser's location bar, so to recap, for simple routes, you can use the router link directive as an attribute, and set it to a string value, If you're dealing with route parameters, you should use the property binding syntax and set the value of this property to an array.
The first element in this array is the path, and the subsequent elements are route arguments. So currently we have a problem in this application. The followers link in the navigation bar is always highlighted. So if you go somewhere else, the followers link is still active. Let's see how we can fix this problem.
In navbar.component.html, here we have this class active. This is part of bootstrap. So if you apply the active class on an li in a navigation bar, the corresponding link will be highlighted. Now we want to apply this dynamically.
So we have another directive called router link active so just like we have router link we also have router link active and as the value here we set a string that includes a list of CSS classes that should be applied when this link is active so here we have only one CSS class that is active we can add more space current so all these classes should be separated by a space now similarly I'm going to apply the same directive to the second li like this now let's test the application back in the browser so currently we are on the posts page and you can see the posts link and the nav bar is selected if i click on followers now the followers link is active and if we inspect this element so here's the li for this link look at the class attribute Here we have two classes, active and current. So we use the router link active to set the CSS class for the selected links in the navigation bar. So in app module, we have defined this route that takes a parameter, username. Let me show you how we can extract this parameter in our github profile component.
Because in a real world application, most likely we want to get this parameter and use a service to get the profile of the given user. So let's go to github profile.ts So here in github profile component, in order to get access to route parameters, we need to inject the activated route class in our constructor. So here I add a parameter called route of type activated route. This is a service that is defined in angular slash router library.
And it's part of the router module that we imported earlier in this section. Now here in ngOnInit we can get the route parameters from this object. So this, the route.pram map.
That's the property that gives us all the parameters in this route. Now look at the type of this property. It's an observable of param map. You have seen observables in the section about consuming HTTP services.
So you know that these observables have a method called subscribe. We can subscribe to them and get values emitted in these observables. So here I'm going to call the subscribe method.
You can see that here we need to pass a function that takes a parameter of type param map and returns void. So let's add an arrow function here, param map, or we can call it params. It's shorter. Goes to a code block. Now let's log this on the console and see what is inside this object.
So console.log params. Save. Back in the browser. So here in the list of followers, I'm going to click the first follower. Now let's take a look at the console.
So this is the object we get. It has two properties, keys and params. Let's look at the keys. So here we have only one key and that is username. Because in app module, we set the name of our parameter to username.
Okay? Now this object also has another property that is params. And here we have key value pairs for route parameters and their values So this is the structure of a prime map object Now back here in ng on in it.
Let's look at the members defined in this class So prams dot we have get get all has and keys You saw the keys field this field returns all the keys or all the route parameters We use the get method to get the value of a given route parameter, we use get all to get the value of all route parameters, and it has to see if we have a parameter by the given name in this object. So here to get the value of the username parameter, we call the get method like this. Get username. And by the way, what we have here is actually not username, it's user id. So always pay great attention to naming your route parameters, because otherwise you can create confusion for other developers, and this will also increase the cost of maintenance of your applications.
So let's go back to app.module, and change the name of this parameter to id. Now back in github profile component, here we need to get the value of the id parameter, now this method as you can see here in the intellisense returns a string, if you need to work with a number a technique that we use in javascript is to put a plus before this, this will convert the string to a number now we can store it in a variable like id and in a real world application, we most likely send this to a service to get the profile of this user. Something like this, service that get profile and we give it this id. Now we don't need this for now, so let's simply log this on the console. Let's test the application one more time.
So here we have the user id displayed in the console. Now if I go back to the followers list and click on a different user. Now in console we have two entries.
So this is how we get the route parameters. But you might be wondering why this param map is defined as an observable. This makes it a little bit hard to access these parameters. How come we don't have an API like this? So this .route of id.
This would be much easier, right? or potentially we could have this.route.paramap of id, this is easier to work with than an observable so in the next lecture I'm going to answer this question Hi, thank you for watching my Angular tutorial. If you enjoyed this video, please like it and share it with others.
Also, you can subscribe to my channel for free new videos every week. This video is part of my complete Angular course with almost 30 hours of high quality content where you will learn everything about Angular from the basic to the advanced topics all in one course. So you don't have to jump from one tutorial to another.
In case you're interested, You can get this course with a big discount using the link in the video description. And if not, that's perfectly fine. Continue watching as the next section is coming up.