Logo

Angular Core

Routing

From static HTML to a real app. The router is the nervous system of your application – it decides what is displayed when, without reloading.

Do you remember old websites? Every click meant: white screen, waiting, page reload. In a Single Page Application (SPA) like Angular, we want to avoid that at all costs. We want the fluid feel of a native app.

I always imagine the router as a director. The URL at the top of the browser is the script. When the URL changes, the director throws the old component off the stage and brings the new one in. The rest of the app (Header, Sidebar) remains untouched.

1. The Simulation

Observe what happens in the mockup below. Click on the links. You will see: The header remains static, only the content in the "Outlet" changes. The URL switches, but the browser does not reload.

localhost:4200/home
<router-outlet>

🏠 Home

Welcome to the main page of the application.

</router-outlet>

2. Implementation

To make this work, I always need three things: A map (Where does it go?), a placeholder (Where is it displayed?), and a trigger (How do I get there?).

The Map (app.routes.ts)

First, I define the rules. Which URL belongs to which component? The wildcard route (**) is essential. It catches all typos (404) and redirects the user back to safety.

app.routes.ts
import { Routes } from '@angular/router';

export const routes: Routes = [
  { path: 'home', component: HomeComponent }, // Default route
  { path: 'about', component: AboutComponent },
  { path: 'contact', component: ContactComponent },

  // IMPORTANT: The Wildcard (404) must always be the last entry!
  // Angular checks routes from top to bottom.
  { path: '**', redirectTo: 'home' }
];

Stage & Trigger (app.component.html)

Now I need the place where the components should appear. That is the <router-outlet>. For navigation, I use the routerLink directive. Never use href, as it would restart the entire Angular application.

app.component.html
<!-- Navigation Bar -->
<nav>
  <!--
    ❌ NEVER use href="/home" -> This reloads the whole app!
    ✅ ALWAYS use routerLink -> Angular swaps components internally.
  -->
  <a routerLink="/home" routerLinkActive="active">Home</a>
  <a routerLink="/about">About</a>
</nav>

<!-- The Stage: This is where the route components appear -->
<router-outlet></router-outlet>
💡

Pro Tip: Use routerLinkActive='active'. Angular automatically adds the class active to the link when you are on that route. Perfect for highlighting the current menu item.

3. Enterprise Architecture: Modularization

As your app grows, the app.routes.ts file quickly becomes huge and confusing. The solution: We outsource routes into thematic files (e.g., Auth, Admin, User) and merge them at the end.

Step A: Outsourcing

Create, for example, an auth.routes.ts file just for login and register logic.

routes/auth.routes.ts
// routes/auth.routes.ts
import { Routes } from '@angular/router';

export const AUTH_ROUTES: Routes = [
  {
    path: 'login',
    loadComponent: () => import('../auth/login/login.component').then(m => m.Login)
  },
  {
    path: 'register',
    loadComponent: () => import('../auth/register/register.component').then(m => m.Register)
  }
];

Step B: Merging (Spread Operator)

In the main file, we import the lists and use the JavaScript spread operator (...) to unpack the arrays into a single flat list. This keeps the main file extremely clean and readable.

app.routes.ts
// app.routes.ts
import { AUTH_ROUTES } from './routes/auth.routes';
import { ADMIN_ROUTES } from './routes/admin.routes';

export const routes: Routes = [
  // The Spread Operator (...) unpacks the arrays into one flat list
  ...AUTH_ROUTES,
  ...ADMIN_ROUTES,

  // Base Routes
  { path: '', component: HomeComponent },
  { path: '**', redirectTo: '' }
];
💡

Route Order: Make sure the wildcard route (**) is always at the very end of your merged list. Angular processes routes from top to bottom. If the wildcard is at the top, it will catch every route below it (causing a 404).