Angular Routing Guide: How to optimize app navigation
Tags: angular, routing, webdev, tutorial
Published: 2021-02-10 23:08:33

Angular is one of the most **popular front-end frameworks**, with 30% of developers preferring it for their projects. Angular is especially useful for large scale projects with many different views and components.
 
The key to making these large scale projects engaging is a logical navigation structure that allows users to easily explore and revisit pages. Thankfully, Angular's routing functionality makes optimizing navigation simple.
 
Today, we'll learn more about Angular Router's capabilities and help you make a fully navigable app.
 
 
**Here’s what we’ll cover today:**
 
* [What is Angular Router ](#what)
* [What are Wildcard Routes](#wildcard)
* [Child Routes](#child-routes)
* [The RouterLink Directive](#routerlink)
* [Adding ActiveLink Styles](#activelink)
* [Lazy loading modules](#lazy-loading)
* [What to learn next](#next)


<br>
<h4><b> Design complex Angular apps with ease </b> </h4>
 
Learn to use all the best Angular tools to create stunning and efficient web apps.
 
<b>[Angular: Designing and Architecting Web Applications](https://www.educative.io/courses/angular-designing-architecting-web-apps)</b>
<br>

<a name="what"></a>
 
## What is Angular Router?
The **Angular Router** is an importable package built-in to Angular 2+ by default. It's used to build Single Page Applications with multiple views that can be navigated by [URL](https://www.educative.io/blog/behind-the-screens-what-happens-when-you-type-a-url-in-a-browser), known as "routing". 
 
URLs consist of a domain name and a route definition, known as a path. A path is a JavaScript object that the server uses to access a specific resource in the [database](https://www.educative.io/blog/database-design-tutorial). When the server serves our application, Angular will grab the path from the URL and match it against any valid paths we've set up. Essentially, we set a [key/value relationship](https://www.educative.io/blog/what-are-database-schemas-examples) with a path like `/blog` as the key and the desired page as the `value`. 
 
This allows users to easily navigate your app and visit the page they want without having to start at the home component. Routing enables support for common browser behaviors like forward/back arrows and page bookmarking.
 
Router also contains tools for advanced behaviors like multiple router outlets, different path matching strategies, easy access to route parameters, and route guards to protect components from unauthorized access.
 
<Br>

### Routing Module and RouterOutlet 
Routing Modules are special Angular modules that define new routes and help configure the router. All routing modules have the suffix `-routing` after their name, which is automatically added by [Angular CLI](https://www.educative.io/blog/angularjs-tutorial). 

Every routing module sets the routing behavior for a paired module with the same base name. For example, the routing behavior for our `home` module would be in the routing module `home-routing`. 
 
Here's an example of a routing module for our `home` module, called `home-routing.module.ts`:

```js
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { HomeMainComponent } from './home-main/home-main.component';
 
const routes: Routes = [
  { path: '', component: HomeMainComponent }
];
 
@NgModule({
  imports: [RouterModule.forChild(routes)],
  exports: [RouterModule]
})
export class HomeRoutingModule { }
```

You can find our routes in the `routes` array variable. Each element of the `routes` array represents the route to a single component view. 

The elements consist of two parts, the `path` property that provides a URL path and the `component` property that defines which component will be loaded at the provided path. 
 
In this case, we enter an empty string (interpreted as a forward slash) to indicate that this component is our homepage and should load if someone just enters the domain name. We then enter the name of the component Angular should fetch as our homepage, `HomeMainComponent`.
 
> We can also use `redirectto` to direct empty path URLs to another page if we'd prefer users land elsewhere.
 
Next, we'll need to remove `HomeMainComponent` from the exports of `HomeModule`. This use of routing means we're no longer exporting the component and instead let Router take care of loading the component if a user visits the route.
 
Finally, we'll replace the contents of the `app.component.html` file with the line: 
 
```
<router-outlet></router-outlet>
```
 
Here, `<router-outlet>` acts as a placeholder for the component. Instead of defining a component, our template will simply pull whatever component is rendered with the passed URL path. By using this placeholder, we don’t have to export the component. Instead, we can export the module.
 
You can now view this app by entering `http://localhost:4200` in your browser address bar.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/gexld6m7ngeqvmvi4hp3.PNG)

To review, the `HomeRoutingModule` is a routing module where we define routes. We have one route that consists of a blank path. We’ll check if the client's URL entry matches that path. If they are, we’ll load the homepage via `HomeMainComponent`.
 
The homepage component is available due to a series of imports. First, we import the `home-routing` module into its paired standard module `home`. Then, we import the `home` module into the app module. Finally, we use the `<router-outlet>` directive in the `app.component.html` file to load the `HomeMainComponent` registered in the original 
`routes` array.
 
<br>
 
<a name="wildcard"></a>
 
## What are Wildcard Routes?
*What happens when a user enters an invalid path?* We can avoid an error by including a **Wildcard Route**, which catches all unregistered paths and directs them to a certain page. You can think of Wildcards as an "other" category that reads as a match to any unregistered paths.
 
Most sites have a Wildcard that directs to a "404 Page Not Found" page. To create an error component for our app, enter the following into your command prompt:
 
```
ng generate component PageNotFound
```
> We do not need a module because this error screen will just be simple text. 
 
You can set a Wildcard by entering `**` in place of a standard path in the `routes` array. 
 
```js
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { PageNotFoundComponent } from './page-not-found/page-not-found.component';
 
const routes: Routes = [
  { path: '**', component: PageNotFoundComponent }
];
 
@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }
```
 
Now, any invalid URL will redirect to our 404 error page. 
 
We need to make sure this component is imported last in the `app.module.ts` file for our other components to load properly. This is because Angular loads the component from the first matching path. If `AppRoutingModule` is imported first, Angular would always load `PageNotFoundComponent` because the Wildcard would always read as a match and therefore Angular would return that component. 
 
```js
  imports: [
    BrowserModule,
    HomeModule,
    AboutModule,
    ContactModule,
    AppRoutingModule,
  ],
 
```
 
The Wildcard at the bottom of the `imports` array ensures that any valid matches are returned and the 404 is only returned if there are no other matches.

<br>
 
<a name="child-routes"></a>
 
## Child Routes
Sometimes it makes sense to have routes categorized as a subgroup within a route. For example, our "About Us" page could feature separate subpages for info on the employees, `/about/team` and info on past clients, `/about/clients`. Child components are only rendered if the user is on the parent `/about` path.
 
First, we'll generate the components by entering the following into our command prompt:
```js
ng generate component about/team
ng generate component about/clients:
```
 
We then set these as children of the "About Us" page by adding a `children` array property to the `about` route in `about-routing.module.ts`. 
```js
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { AboutMainComponent } from './about-main/about-main.component'
import { BioComponent } from './bio/bio.component';
import { TeamComponent } from './team/team.component';
import { ClientsComponent } from './clients/clients.component';
 
const routes: Routes = [
  {
    path: '',
    component: AboutMainComponent,
    children: [
      { path: '', component: BioComponent },
      { path: 'team', component: TeamComponent },
      { path: 'clients', component: ClientsComponent },
    ]
  }
];
 
@NgModule({
  imports: [RouterModule.forChild(routes)],
  exports: [RouterModule]
})
export class AboutRoutingModule { }
 
```
 
The `children` array acts like a smaller version of the `routes` array, with similarly-formatted `path` and `component` properties. The difference is that child routes' path properties are appended onto their parent path, meaning you do not need to write the full path.
 
For example, the full path to reach `TeamComponent` would be `/about/team` rather than just `'/team'`.
 
Finally, we'll update the `about-main.component.html` template file with `<router-outlet>` to let it show any of the child components of `about`. 
 
```html
<h1>About Page</h1>
 
<router-outlet></router-outlet>
```
 
<br>
 
 
<div style="background-color:#F1F1FF;padding-left: 10px;padding-top:1px;padding-bottom:1px;">
 
#### Continue learning Angular.
Pick up Angular in half the time. Educative's hands-on courses let you learn top industry skills with real-world practice, not lengthy video lectures. By the end, you'll know how to create fully-fledged Angular apps.
 
<b>[Angular: Designing and Architecting Web Applications](https://www.educative.io/courses/angular-designing-architecting-web-apps)</b>
</div>
 
<br>

<br>
 
<a name="routerlink"></a>
 
## The RouterLink Directive
Most apps will allow users to navigate with a specific URL and user-clicks on link elements. We'll need Bootstrap to add links. You can make links using standard `href` attributes. However, that requires the site refresh and assets reload whenever the page changes.
 
We can speed up loading using Angular Router's `routerLink` directive, which leverages history API to let Angular access your immediate browser history. This means browsers only need to load each page once, as any later visits can display the previously loaded elements.
 
To implement `routerLink`, replace the contents of `app.component.html` with:
 
```html
<nav class="navbar navbar-expand-md navbar-light bg-light mb-4">
  <a class="navbar-brand" routerLink="/">Website</a>
 
  <div class="collapse navbar-collapse">
    <ul class="navbar-nav mr-auto">
      <li class="nav-item">
        <a class="nav-link" routerLink="/about">About</a>
      </li>
      <li class="nav-item">
        <a class="nav-link" routerLink="/contact">Contact</a>
      </li>
    </ul>
  </div>
</nav>
 
<main class="container">
  <div class="card">
    <div class="card-body">
      <router-outlet></router-outlet>
    </div>
  </div>
</main>
```
 
The URL in the address bar will still change when navigating through these links, but the browser will not refresh the page or reload assets on return visits.
 
<br>
 
<a name="activelink"></a>
 
## Adding ActiveLink Styles
Building on our new navigation links, we also need a way to tell the user which page they're currently on. The best way to do this in Angular is to use the `active` class, which will change the style of a link if they're currently on to indicate it is active. 
 
In Bootstrap, the `active` class can be applied to the `<li>` element wrapped around the `<a>` element. We'll use Angular's `routerLinkActive` directive to achieve this.
 
```html
<nav class="navbar navbar-expand-md navbar-light bg-light mb-4">
  <a class="navbar-brand" routerLink="/">Website</a>
 
  <div class="collapse navbar-collapse">
    <ul class="navbar-nav mr-auto">
      <li class="nav-item" routerLinkActive="active">
        <a class="nav-link" routerLink="/about">About</a>
      </li>
      <li class="nav-item" routerLinkActive="active">
        <a class="nav-link" routerLink="/contact">Contact</a>
      </li>
    </ul>
  </div>
</nav>
 
<main class="container">
  <div class="card">
    <div class="card-body">
      <router-outlet></router-outlet>
    </div>
  </div>
</main>
```
 
We’re applying the directive on the `<li>` elements with the `nav-item` class. This directive will check if the URL in the address bar matches the path in the `routerLink` directive. 

If the path matches, we'll add it to the `active` class to change the link text to show that it's active with the darker text color. 

<br>

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/q9apg1wn5w5gzg2mjc38.PNG)

<br>
 
<a name="lazy-loading"></a>
 
## Lazy loading modules
 
We can improve the performance of our module by transitioning from **eager loading** to **lazy loading**. 

Eager loading is when the browser is directed to load all components within the `app` module, regardless of which it will use.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/zvd5nxqlumf4w0vbcq4e.PNG)

 Lazy loading instead splits the module into separate files so the app only loads the components it needs for the current page render. Lazy loading is often preferred as it allows the page to load the minimum amount of data for each render and therefore speeds up loading. 

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/1jnb2dimkc652s7ry31f.PNG)

To implement lazy loading, we first remove all module imports from `app.module.ts`:
 
```js
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
 
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { PageNotFoundComponent } from './page-not-found/page-not-found.component';
 
@NgModule({
  declarations: [
    AppComponent,
    PageNotFoundComponent,
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }
```
We still eager load `PageNotFoundComponent`, as it is low weight, and we could need it at any point. 
 
We also need to update this information in the `routes` array found in `app-routing.module.ts`. This is the only routing module that will be sent at the user's initial request. Angular can then use this file to load any future modules as needed.
 
```
const routes: Routes = [
  { path: '', loadChildren: () => import('./home/home.module').then(m => m.HomeModule) },
  { path: 'about', loadChildren: () => import('./about/about.module').then(m => m.AboutModule) },
  { path: 'contact', loadChildren: () => import('./contact/contact.module').then(m => m.ContactModule) },
  { path: '**', component: PageNotFoundComponent },
];
```
Notice that we’re not using the component property to tell Angular what component to load when the route is visited. Instead, we’re using the `loadChildren` property. This will tell Angular to lazy load a module. We’re setting it to an arrow function, which will request the module through the `import()` function. The `import()` function returns a promise. We chain the `then()` function to handle the response.
 
These `loadChildren` paths will pass along any previous path elements as a prefix for later paths. We must therefore update each of our routing modules' `Routes` array to empty paths to ensure we do not repeat path names like `/about/about`. 
 
```js
{ path: '', component: AboutMainComponent }
```
 
<br>
 
<a name="next"></a>
 
## What to learn next
 
Congratulations on making a fully navigable Angular application! Routing is the key to keep users engaging with your app, especially for large applications. However, it's just one part of making an excellent Angular app. 
 
Here are some **more advanced concepts** you're ready to tackle along your Angular journey:
- Advanced Routing (private routes, pairing CSS stylesheets)
- Lifecycle Hooks
- Modal Components
- Authentication
- Dependencies
 
To help you study these topics, Educative has created [**Angular: Designing and Architecting Web Applications**](https://www.educative.io/courses/angular-designing-architecting-web-apps). This course teaches you how to create large scale Angular applications in a logical and efficient way using advanced Angular techniques. You'll even build a full-fledged application alongside the course. 

By the end, you'll have hands-on experience, plus a project for your professional portfolio.
 
*Happy learning!*

<br>
 
### Continue Reading about Angular 2+ and front-end development
- [Angular tutorial: Getting started with Angular 2+](https://www.educative.io/blog/angularjs-tutorial)
- [Angular vs Vue vs React: choosing the best framework in 2020](https://www.educative.io/blog/react-angular-vue-comparison)
- [RxJS Tutorial: Observables, Operators and beyond](https://www.educative.io/blog/rxjs-tutorial-observables-operators)