Intro to Routing in Angular 5

Kevin Rejko
6 min readApr 20, 2018

While the Angular framework is known for creating single page applications, updating the URL in the address bar can make your website significantly easier to use. By adding routes to your application, users can

  • refresh the page without losing their place
  • save a bookmark for a particular feature or piece of data
  • share links to a particular part of your site with others

Routing at a High-Level

Angular web applications are accessed by loading the hostname of the application in a web browser. When building the application on a local machine, this will commonly look like this:

http://localhost:4200

As an application grows, it is typical for new features to be added. These feature components can be displayed without routing using directives (such as ‘ngIf’), but this approach becomes more difficult to maintain as the application grows and has the downside of not allowing a user to directly navigate a place in the application.

To solve this, we can use Angular’s RoutingModule to name our feature components and load them automatically when the component’s name is appended to our app’s hostname:

http://localhost:4200/feature_component_name

While in the above example, it may not look intuitive, once routing is implemented using real features on a deployed application, it becomes significantly easier to understand.

http://www.music.com/artists
http://www.music.com/albums
http://www.music.com/tracks

The above routes would take a user to view a list of artist, albums, and tracks.

Angular’s RoutingModule

The RoutingModule provided with Angular (in ‘@angular/router’) is responsible for keeping the application in sync with the address bar and vice versa.

Additionally, Angular’s routing package can also facilitate redirects, route parameterization, hash fragments, nested routes, wildcards, and executing custom functionality before or after a route navigation (also called guards). If you don’t know what some of these features are, don’t worry; They will be covered in a later article.

RoutingModule Requirements

In order for the RoutingModule to function, the application must have the following updates:

Import Dependancies

For the application to know we want to use routing, we must import the RoutingModule and Routes object from @Angular/router into your app’s module.

import { RouterModule, Routes } from ‘@angular/router’

Define Routes

To know the features names supported in the app, routes must be defined. These routes will connect the feature names (or ‘path’) to the component that the RouterModule should load:

const appRoutes: Routes = [
{ path: ‘’, component: HomeComponent }
{ path: ‘artists’, component: ArtistsComponent },
{ path: ‘albums’, component: AlbumsComponent }
]

Linking Routes to our Application

For the RoutingModule to know of our routes, we must provide the routes using the ‘forRoot()’ method. To connect our RoutingModule to our application, we will add our RoutingModule to the imports of our app’s module:

@NgModule({
imports: [
RouterModule.forRoot(appRoutes)
],
...
)}

Displaying a Routed Component

With the above steps, the AngularRouter will know which component to display, but will not know where it should be displayed. To fix this, we must replace the default loaded feature component with the router’s component so that only the routed feature is displayed

<!-- One possible app.component.html --><app-header></app-header>
<div class=”container”>
<div class=”row”>
<!-- <default-feature></default-feature> DELETE THIS -->
<router-outlet></router-outlet> <!-- ADD THIS -->
</div>
</div>

Basic Implementation

Putting it all together should look something like this:

app.module.ts

import { BrowserModule } from '@angular/platform-browser';
import { Routes, RouterModule } from '@angular/router'
import { AppComponent } from './app.component';
import { ArtistsComponent } from './artists/artists.component';
import { AlbumsComponent } from './albums/albums.component';
const appRoutes: Routes = [
{ path: ‘’, component: HomeComponent }
{ path: ‘artists’, component: ArtistsComponent },
{ path: ‘albums’, component: AlbumsComponent }
]
@NgModule({
declarations: [
AppComponent,
ArtistsComponent,
AlbumsComponent
],
imports: [
BrowserModule,
RouterModule.forRoot(appRoutes)
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }

app.component.html

<!-- One possible app.component.html --><app-header></app-header>
<div class=”container”>
<div class=”row”>
<!-- <default-feature></default-feature> DELETE THIS -->
<router-outlet></router-outlet> <!-- ADD THIS -->
</div>
</div>

At this point, the following URLs should now load their corresponding components.

http://localhost:4200/
http://localhost:4200/artists
http://localhost:4200/albums

Load Route Programmatically

While this certainly is a great start, many users won’t know these routes the first time they visit the application. It will be more common for these users to start at the app’s home page, and then navigate to different features using links, menus, and buttons.

Templates

While you might think this can easily be done by adding the route to the href tag of an anchor, I would strongly caution against this approach. The href attribute can cause the page to reload from the server which will slow down the application and can cause your site to be more expensive to host. Additionally, this reload may also clear out some of our user’s selections which would make the application frustrating, difficult, and time-consuming to use.

Instead, the RoutingModule provides an attribute that can be added to anchor tags in place of ‘href’ called ‘routerLink’. ‘routerLink’ functions similarly to ‘href’ but communicates directly with the RouterModule instead of reloading the page.

<a routerLink="albums">Albums</a>

TypeScript

Another common use case is to navigate a user to a different page after an action has been completed, such as successfully saving some data. In this case, the route navigation action will be triggered in our TypeScript code instead of automatically from our template.

This is done by injecting Angular’s ‘Router’ service into the constructor of the component and using the ‘navigate()’ function passing the path as a parameter.

export class HomeComponent {    constructor(private router: Router) { }    onSelected(){
//Do Something
router.navigate(['albums']);
}
}

Notice that the path parameter is an array. Later, this can be useful for more advanced cases such as nesting sub routes.

Indicate a Selected Route

It can be helpful for users to see their current location in the app to assist with understanding your app’s navigation. This can be done by applying a style to any elements that link to the currently routed component.

Angular’s RoutingModule provides a directive for exactly this purpose: routerLinkActive. When an element contains a link to the current route, the class provided to the routerLinkActive dirictive will be automatically applied to the element.

<ul class="nav navbar-nav">
<li routerLinkActive="active">
<a routerLink="albums">Albums</a>
</li>
<li routerLinkActive="active">
<a routerLink="artists">Artists</a>
</li>
</ul>

Additionally, if the route changes, routerLinkActive will also update removing any classes for routes no longer displayed. So, for the example above, only one ‘active’ class will be applied to a link at any given time.

Pitfalls and Gotchas

Below are a couple of common issues and how to overcome them.

No Home Route

If a home route is not defined (path: ‘’), the router will be unable to load a component when the root of the application is visited. This issue can be difficult to debug because this undefined route does not throw an error in the browser’s console.

To fix this, a home route must be defined. This can be done by either providing a link to a ‘home’ component or by redirecting to a different route:

// Adding Home Component 
{ path: ‘’, component: HomeComponent }
// Redirection
{ path: ‘’, redirectTo: 'albums', pathMatch: 'full'},
{ path: ‘albums’, component: AlbumComponent }

By adding an ‘href’ to existing anchor tags, it can signal that the page should be refreshed instead of a new component being loaded. This can be seen when the selected route component does not display after it has been selected.

In this case, the ‘href’ attribute of the anchor tag (<a>) can simply be omitted.

Additional Information:

For further reading, examples, and advanced functionality, I would highly recommend taking a look at the Routing & Navigation page provided on the angular website.

Conclusion

Congratulations! You now know what routing is, why it’s useful, and the basics of how it could be added to an Angular 5 application.

Please share any questions or comments. Thanks for reading!

--

--