DEV Community

Cover image for How to set up routing in Angular to create single-page applications
Ekekenta Clinton
Ekekenta Clinton

Posted on

How to set up routing in Angular to create single-page applications

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:

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
Enter fullscreen mode Exit fullscreen mode

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

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

cd my-music-library
Enter fullscreen mode Exit fullscreen mode

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 {}
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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)
    })
  }
}
Enter fullscreen mode Exit fullscreen mode

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 { }

Enter fullscreen mode Exit fullscreen mode

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)
      })
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

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"
  }
]
Enter fullscreen mode Exit fullscreen mode

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"
 ],
 ...
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

This code defines a heading for the application, a navigation link that points to the /albums path, and a 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
Enter fullscreen mode Exit fullscreen mode

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

So when you click on any of the links, you'll be redirected to the details page.

Displaying individual musics for each post id

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.

Top comments (2)

Collapse
 
renancferro profile image
Renan Ferro

Hey friend, how are you?!

Nice article! When using code blocks we can pass the "type" of code as a parameter, see:

Image description

Collapse
 
codev206 profile image
Ekekenta Clinton

Thanks for that oversight