Introduction to Angular Routing
Welcome back, friends. The application is coming along and we're ready for the next step, routing.
Routing is our way of navigating between components which represent our pages. It's the same as when you visit a website and click on a link and are navigated to a different page. To accomplish this in Angular, we will use the Angular router.
If a user of the home's application wants to investigate a given property, they need a way to find out more details. We'll create a details component and we'll add routing support so that users can navigate to that new component.
Enabling the Angular Router
We need to configure the application to support routing and route to this component. During setup, we could have included routing and some of this configuration automatically. But I thought it would be more fun for us to add it ourselves.
To start things off, we need to enable routing in the application. In main.ts, import provideRouter, wrapped in curly braces, from at Angular forward slash router. The provide router function sets up the required functionality for our app to support routing.
As a second parameter to bootstrapApplication, add a JavaScript literal with one property call providers. Set the provider's property value to be an array. Then, as an entry to the array, add a call to the provideRouter function while passing in an empty array as a parameter. This empty array represents our application routes. Routes define which path link to components in the application. We haven't defined any routes just yet. We're going to take care of that and then return here to replace this array.
Creating a Routes File
To create the routes, we'll first start by creating a file under source/app called routes.ts. Open routes.ts and let's update it by adding the following. Import Routes -- that's with a capital R -- from @angular/router, HomeComponent from ./home/home.component.
Next, let's create a const variable called routeConfig -- that's camel case -- and make that of type Routes. Assign it a value of an empty array. We'll update this in just a moment.
We need the routeConfig variable to be available to files that import our routes. So let's add an export line, export default routeConfig.
Configuring the App Component for Routing
Next, we need to update the application to display components based on the current route. Now, we'll do that in app.component.ts. Start by importing RouterModule, wrapped in curly braces, from at Angular forward slash router. Then update the imports array of the component metadata and add RouterModule as an entry to that array.
Now we can use features of the router in our application. Great. In the template for this component, replace the child contents of the section with the content class with the router-outlet directive. Use the same syntax that we use to reference components in a template, because we'll follow that same pattern, which is using angle brackets to surround the element name. While this directive has similar syntax to our components, take note that in this case we're adding functionality with the directive, but not including a template.
This is where each component that we route to will be displayed. Now, we didn't change any of the surrounding HTML. That HTML will persist between pages as we navigate through the application. If we save the application and check the browser, it will display a blank screen with just a header. Now, this is expected behavior because we haven't defined any routes just yet.
Defining the Default Home Route
Let's update the app and fix this. A great next goal would be getting the homepage to display again. Well, let's handle that now. In routes.ts, we need to create a route for the home page. In the routeConfig array, let's add a new entry. This entry is an object literal that represents a route.
Inside the object literal, add a path property with the value of empty string. The path represents which URL matches which component. When users visit the app, we want them to be routed to the home component by default. That's why this path is empty. Add another property called component and set the value to be the HomeComponent class.
To make our application even better, we're going to also set the page title for each route. To do that, add a title property and set it to the string value home page. Save this code.
In main.ts, we're going to update the application to use our new routes.ts route definitions. Let's add an import to the file import list. Import routeConfig camel case from ./app/routes. Now, in this case, don't surround routeConfig in curly braces. This gives us access to the routeConfig property that we defined. Now, we're going to update the provideRouter function call in the providers array by replacing the empty array with our routeConfig value.
Save this code and return to the browser. Now, in the browser, we find a rendered home page. The default route now routes users to the HomeComponent. Now, this is great progress so far. Excellent work.
Generating the Details Component with the CLI
Let's make some more updates to navigate to the details view for each property. Let's start by creating the details component with the Angular CLI. From the command line, run the following command, ng g c details --standalone --inline-template.
We're using abbreviations with this command. So let's cover each one to ensure that everyone is able to follow along.
ng is the Angular CLI.
g is the short form of generate.
c is the short form of component, which is what we're generating.
details is the name of the component.
standalone instructs the CLI to generate the component as a standalone component.
inline-template instructs to CLI to include a template property in the component decorators metadata.
I use this setup to reduce the number of files generated and to save myself some typing later. All right, we've generated the details component, and it's available in our project structure.
Creating a Route and Link to the Details Page
Now, we need a route so that users can navigate to the component. We're going to make two updates. First, we're going to add a new route to the routes.ts file. Second, we're going to add a link to the Details page to the housing list component.
In routes.ts, let's import DetailsComponent from ./details/details.component. Next, add another entry to the routeConfig array. In the object literal for the new entry, add a path property with the string value details. Then add a component property with the value being a reference to the DetailsComponent that we just imported. And, finally, add a title property with the string value details page.
In housing-location.component.ts, we need to update the template property of the component decorator metadata to include an anchor element as the last child of the section element. Set the display text of the anchor to learn more.
At this point, we're going to take advantage of some of Angular's powerful routing features. Instead of adding an href attribute to the anchor element, we'll add a routerLink directive. This directive allows us to extend the functionality of the anchor element that makes working with app navigation more convenient.
First, we need to import the RouterModule from @angular/router. Next, update the component decorator metadata imports array, adding another entry for RouterModule. Now, update the anchor element to include a routerLink—and that's camel case—attribute, and assign it the string value /details.
Save this code and check the browser. Now, in the browser, we find a link beneath each listing. Fantastic. This is exactly what we want.
Passing Data with Parameterized Routes
Now, let's click on a given link to view the details for the housing location listing. Wait, what happened here? Well, we navigated correctly to the Details page. But there are two things missing from this page. First, we haven't added any template or styling code. We already know how to solve that problem. We'll update the template with the appropriate code.
But there's a second issue that we have to resolve. How will we know which housing location to display the details for? We need some way to identify which housing location the user clicked on so that we can display the correct data. In Angular, there are multiple ways to solve this problem. We can pass data directly to the route by taking advantage of some router features, like being able to pass state and data to a route. Or we can instead pass some sort of identifier via the URL and then reference the housing location by that ID.
In this case, we're going to follow the latter path and send information to the details route via the URL. In housing-location.component.ts, we need to update the anchor element in the template of the component. First, surround the routerLink directive in square brackets. Now, this is for property binding. And it means that the right-hand side value will support dynamic values and more than just strings. This will come in handy in a moment.
As for the value of the router link, we're going to update it to be an array with the first entry being the string /details. The next entry will be housingLocation.id. Now, be sure to wrap this entire value in quotes. Now, I'm using double quotes to wrap the value. And then, for the details path, I used single quotes. Save this code, and we'll move on to the next step.
Configuring a Parameterized Route Path
The Learn More links now have a new URL, /detail/ a number, whatever the specified ID is. Perfect. But if you were to test this code right now in a browser, it would not work because there is no route that matches this path.
In routes.ts, there are only two routes to find, the default empty path route and the details route. If we want that to match against the URLs we just created, then we need to define a route that matches that format. Specifically, we need it to be able to match the URL format /details/ another value that we don't know beforehand. We'll use parameterized routes in Angular for this job.
Let's update the routes in routes.ts. In the route configuration, update the details route entry. Set the path property to details/:id. The :id portion is a placeholder for the parameter value we'll receive in the URLs that match against this route. If we save this code and check the browser, the links to the Details page are working again. This is wonderful. The URL is unique for each of the housing locations, which means that we now have a way to display the correct details for each selected housing location.
Accessing Route Parameters in a Component
In details.component.ts, we're going to update the code to get access to that URL parameter so we can use it in our component.
Let's import inject from @angular/core, as well as import ActivatedRoute from @angular/router. Next, in the body of the DetailsComponent class, we'll add a property class route of type ActivatedRoute. The activated route is a reference to the current route we're matched against in the application. From there, we can get access to the vital route information, including the parameters we need to find our data.
Also, let's create another property called housingLocationId, and set the value to 0. Next, create a method that accepts no parameters named constructor. We'll make our next changes in the body of the constructor. Assign this.housingLocationId the value this.route.snapshot.params['id'].
Now, we expect the ID to be a numeric value. So let's convert it to a number by passing this entire right-hand side expression to the Number class. But we don't need to instantiate a new instance here.
Finally, let's update our template in the component decorator metadata. Use interpolation to append housingLocationId to the details work text. Save this code, and let's check the browser. Clicking on the Learn More link now navigates to a customized details page. Each page renders the ID on the screen. Now, I can guess what you might be thinking. What about the rest of the detail for the housing location? Great questions. And we're going to solve those in the next section.
Recap and Next Steps
Friends, we've done some really great work in this section. We've learned how to navigate in our application using the Angular router and the routerLink directive. We've learned how to pass information to a route using the parameterized routes and retrieve information from a route and a component using the ActivatedRoute feature. In the next section, we'll continue our journey. So catch you in the next one.