How to set up routing in Angular to create single-page applications
Tags: javascript, angular, opensource, tutorial
Published: 2023-04-19 22:40:04

In this tutorial, we will cover how to set up routing in an Angular application to create a single-page application. Routing allows users to navigate between pages without a full page reload, providing a more seamless and responsive user experience. We will use a real-world demo application called **My Music Library** to illustrate how to implement routing in Angular.

The **My Music Library** application will have multiple pages, each displaying different details about an album. Implementing routing will allow users to navigate between these pages and view different album details without the need for a full page reload. This tutorial will cover the challenges faced when creating a single-page application, such as maintaining application state and providing a smooth user experience, and how to overcome these challenges using Angular routing.

## Prerequisites
Before we begin, you should have the following installed on your machine:

- [Node.js](https://nodejs.org/en)
- [Angular](https://angular.io/docs) CLI

## Understanding Routing in Angular
Routing is the process of navigating between pages or views in an application. In Angular, routing is used to create a single-page application (SPA) where the content is loaded dynamically without refreshing the page.

### Routing in Angular and its purpose.

Routing in Angular is the mechanism used to navigate between different components and views within a single-page application. It allows us to define different URLs for different components, and when the user navigates to a particular URL, the corresponding component is displayed without reloading the page. This provides a seamless user experience and improves the performance of the application.

### Types of routing in Angular
There are two types of routing in Angular: Client-side routing and server-side routing.

**Client-side routing**: Client-side routing is the most common type of routing in Angular. In client-side routing, the routing logic is handled by the Angular router in the browser, and the server only serves the initial HTML page. When the user clicks a link or enters a URL, the Angular router intercepts the request and loads the corresponding component into the view without refreshing the page.

**Server-side routing**: Server-side routing is less common in Angular, but it's still an important concept to understand. In server-side routing, the routing logic is handled by the server, which generates the HTML for each page and sends it to the browser. When the user clicks a link or enters a URL, the server generates a new HTML page and sends it back to the browser. This approach is useful for applications with a lot of dynamic content or for SEO optimization.

### How does routing work in a single-page application?
In a single-page application, all the content is loaded dynamically, and the URL is used to navigate between different components and views. When the user clicks a link or enters a URL, the Angular router intercepts the request and matches it to a route defined in the application. Once a matching route is found, the corresponding component is loaded into the view, and the URL is updated to reflect the new state of the application. The user can then navigate back and forth between different components by clicking links or using the browser's back and forward buttons, and the content is loaded dynamically without reloading the page.

Routing in Angular is a powerful and flexible feature that allows developers to create rich and interactive single-page applications with ease. By understanding the concepts and principles of routing, you can create applications that provide a seamless and engaging user experience.


## Setting up Angular Routing
To begin, let's use the Angular CLI to create a new Angular application. Run the command below in your terminal or command prompt:

```
ng new my-music-library
```
When you run the ng new command to create a new Angular application, you will be prompted with a series of questions to configure the project. Here's a breakdown of the prompts and the recommended selections:

- **Would you like to add Angular routing? (y/N)** - Answer y to add Angular routing to your application. This will generate a separate routing module that you can use to define your application routes.

- **Which stylesheet format would you like to use? (Use arrow keys)** - Use the arrow keys to select your preferred stylesheet format. The default is CSS, but you can also choose Sass, SCSS, Less, or Stylus.

After the selections, the command will create a new Angular application called `my-music-library`.

![selecting the prefered options for your application](https://i.imgur.com/xXzmc7a.png)

Next, change directory into the project folder by running the command below:


```
cd my-music-library
```

## Creating Multiple Routes in Angular
Let's define some routes for our **My Music Library** application. We will have two main views: a list of albums and a detail view for each album. To define these routes, replace the contents of the `src/app/app-routing.module.ts` file with the following code:

```
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { AlbumListComponent } from './album-list/album-list.component';
import { AlbumDetailComponent } from './album-detail/album-detail.component';

const routes: Routes = [
  { path: '', redirectTo: '/albums', pathMatch: 'full' },
  { path: 'albums', component: AlbumListComponent },
  { path: 'albums/:id', component: AlbumDetailComponent },
  { path: '**', redirectTo: '/albums' }
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule],
})
export class AppRoutingModule {}
```

This code imports the `AlbumListComponent` and `AlbumDetailComponent` and defines three routes:

- The empty path redirects to the `/albums` path.
- The `/albums` path loads the AlbumListComponent.
- The `/albums/:id` path loads the AlbumDetailComponent with the corresponding album ID.
- The `**` path redirects to the `/albums` path if any other path is requested.

## Creating Components for the Routes
We also need to create the `AlbumListComponent` and `AlbumDetailComponent` that we referenced in the routes. Run the following command to generate the components:

```
ng generate component album-list
ng generate component album-detail
```
This will generate two new components in the `src/app` directory called `album-list` and `album-detail`. Open the `src/app/album-list/album-list.component.ts` file and replace the contents with the following code:

```
import { Component, OnInit } from '@angular/core'
import { HttpClient } from '@angular/common/http'

@Component({
  selector: 'app-album-list',
  templateUrl: './album-list.component.html',
  styleUrls: ['./album-list.component.css'],
})
export class AlbumListComponent implements OnInit {
  albums: any[] = []

  constructor(private http: HttpClient) {}

  ngOnInit() {
    this.http.get<any[]>('/assets/albums.json').subscribe((albums) => {
      this.albums = albums
      console.log(this.albums)
    })
  }
}
```

This code defines the `AlbumListComponent` as a TypeScript class that implements the OnInit interface. It also imports the HttpClient service from `@angular/common/http module`, which allows the component to make HTTP requests.

The `ngOnInit` method is overridden to load the data for the component. In this case, the component makes an HTTP GET request to the `assets/albums.json` file to retrieve a list of albums in JSON format. The subscribe method is used to handle the response and assign the data to the albums property of the component.

Now update the app.module.ts file to import the `HttpClientModule` in your app module and add it to the imports array. 

```
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { AlbumListComponent } from './album-list/album-list.component';
import { AlbumDetailComponent } from './album-detail/album-detail.component';
import { HttpClientModule } from '@angular/common/http';

@NgModule({
  declarations: [
    AppComponent,
    AlbumListComponent,
    AlbumDetailComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    HttpClientModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

```

Next, open the `src/app/album-detail/album-detail.component.ts` file and replace the contents with the following code:

```
import { Component, OnInit } from '@angular/core'
import { ActivatedRoute } from '@angular/router'
import { HttpClient } from '@angular/common/http'

@Component({
  selector: 'app-album-detail',
  templateUrl: './album-detail.component.html',
  styleUrls: ['./album-detail.component.css'],
})
export class AlbumDetailComponent implements OnInit {
  albumId!: number
  album: any
  musicList: any[] = []

  constructor(private route: ActivatedRoute, private http: HttpClient) {}

  ngOnInit() {
    const id = this.route.snapshot.paramMap.get('id')
    if (id !== null) {
      this.albumId = +id
      this.http.get<any[]>('/assets/albums.json').subscribe((albums) => {
        this.album = albums.find((album) => album.id === this.albumId)
        this.musicList = this.album.musicList
        console.log(this.albumId,this.album)
      })
    }
  }
}
```

This updated code defines the `AlbumDetailComponent` as a TypeScript class that injects both the `ActivatedRoute` service and the `HttpClient` service. The ActivatedRoute service is used to get the album ID from the URL parameters, while the `HttpClient` service is used to retrieve the album and music list details from the `albums.json` file.

The `ngOnInit` method first uses the snapshot method of the `ActivatedRoute` service to retrieve the album ID from the URL. It then checks if the ID is not null before casting it to a number and assigning it to the `albumId` property.

After that, the component subscribes to the `HttpClient` service's get method to retrieve the `albums.json` file. The `subscribe` method takes a callback function that receives an array of albums as a parameter. The find method is used to filter and return the album object that matches the albumId. Once the album is found, its `musicList` property is assigned to the `musicList` property of the component.

This approach avoids the need for a resolver, as the data is fetched directly from the `albums.json` file. However, it is worth noting that this approach is less scalable than using a resolver, as the entire `albums.json` file will be fetched each time the component is loaded.

Now create the `albums.json` file in the `assets` directory and add the code below:

```
[
  {
    "id": 1,
    "title": "Thriller",
    "artist": "Michael Jackson",
    "year": 1982,
    "genre": "Pop"
  },
  {
    "id": 2,
    "title": "Abbey Road",
    "artist": "The Beatles",
    "year": 1969,
    "genre": "Rock"
  },
  {
    "id": 3,
    "title": "The Dark Side of the Moon",
    "artist": "Pink Floyd",
    "year": 1973,
    "genre": "Progressive Rock"
  }
]
```
Then add `src/assets/albums.json` to the assets array in the `angular.json` file:

```
...
"assets": [
   "src/favicon.ico",
    "src/assets",
   "src/assets/albums.json"
 ],
 ...
```


## Creating Templates for the Components
Next, we need to create the HTML templates for our components. Open the `src/app/album-list/album-list.component.html` file and replace the contents with the following code:

```
<h1>Album List</h1>

<div *ngFor="let album of albums">
  <h2>{{ album.title }}</h2>
  <p>Artist: {{ album.artist }}</p>
  <p>Year: {{ album.year }}</p>
  <p>Genre: {{ album.genre }}</p>
  <a [routerLink]="['/albums', album.id]">View details</a>
</div>
```

This code defines the HTML template for the `AlbumListComponent`. The code uses Angular's built-in structural directive `ngFor` to loop through the albums array and display the details of each album.

For each album, it displays its `title`, `artist`, `year`, and `genre`. It also creates a link using the `routerLink` directive, which allows the user to navigate to the `AlbumDetailComponent` to view the album's details.

The link is created using an array, where the first element is the route to the `AlbumDetailComponent` and the second element is the `id` of the album being displayed. This array is passed to the `routerLink` directive using property binding syntax `[routerLink]`.

Similarly, open the `src/app/album-detail/album-detail.component.html` file and replace the contents with the following code:

```
<h2>Album Details</h2>
<div *ngIf="album">
  <h3>{{ album.title }}</h3>
  <p>Artist: {{ album.artist }}</p>
  <p>Year: {{ album.year }}</p>
  <p>Genre: {{ album.genre }}</p>
</div>
```

This code defines the layout for the `AlbumDetailComponent` view. It includes an `h2` heading that says `Album Details` and two div elements. The first div element uses `*ngIf` to only display its contents if `album` is defined. It displays information about the `album`, including its `title`, `artist`, `year`, and `genre`.

The second div element also uses `*ngIf` to only display its contents if `musicList` has at least one item. It displays a subheading "Songs" and a list of songs using `*ngFor` to loop through each song and display its `title` and `duration`.

## Adding Navigation Links

Finally, let's add some navigation links to our application. Open the `src/app/app.component.html` file and replace the contents with the following code:

```
<h1>My Music Library</h1>
<nav>
  <a routerLink="/albums">Albums</a>
</nav>
<router-outlet></router-outlet>
```

This code defines a heading for the application, a navigation link that points to the `/albums` path, and a **<router-outlet>** element that displays the component for the current route.

## Running the Application
To run the "My Music Library" application, open your terminal or command prompt and run the following command:

```
ng serve
```
	
This will compile and serve the Angular application at `http://localhost:4200/`. Navigate to this URL in your web browser to see the application in action.
	
![Displaying all the music albums](https://i.imgur.com/INp5LjG.png)

So when you click on any of the links, you'll be redirected to the details page.
	
![Displaying individual musics for each post id](https://i.imgur.com/R0pN4Ma.png)


## Conclusion
	
In this tutorial, we learned how to set up routing in an Angular application to create a single-page application. We used a real-world demo application called **My Music Library** to illustrate this process. We defined multiple routes for the application and created components and templates for each route. Finally, we added navigation links to the application and ran it to see the results. The code for this tutorial is available here on my GitHub [repository](https://github.com/icode247/my-music-library/).