Fortgeschritten252025-01-31

Angular Routing & Navigation - Multi-Page Apps erstellen

Lerne Angular Router kennen, erstelle Routes, navigiere zwischen Seiten, nutze Route Parameters und schütze Routes mit Guards.

#angular#routing#router#navigation#guards#route-parameters

Angular Routing & Navigation

Zeit für Multi-Page Apps! Mit Angular Router erstellst du SPAs (Single Page Applications) mit mehreren Seiten. 🗺️

📋 In diesem Artikel lernst du:

  • Was Angular Router ist und warum du ihn brauchst
  • Router Setup und Konfiguration
  • Routes definieren und verschachteln
  • Zwischen Seiten navigieren (Links & Programmatisch)
  • Route Parameters und Query Parameters
  • Wildcard Routes und 404-Seiten
  • Route Guards (Schutz für Routen)
  • Lazy Loading für bessere Performance

Was ist Angular Router?

Angular Router ermöglicht Navigation zwischen verschiedenen Views/Seiten ohne Page Reload!

Traditionelle Website vs SPA:

Traditionelle Multi-Page Website:

User klickt auf Link
→ Browser lädt NEUE HTML-Seite vom Server
→ Kompletter Page Reload
→ Langsam! ❌

Angular SPA mit Router:

User klickt auf Link
→ Angular Router ändert View (keine Server-Anfrage!)
→ Nur Content wird ausgetauscht
→ Blitzschnell! ✅

Vorteile:

  • ✅ Schnelle Navigation (keine Page Reloads)
  • ✅ Smooth Transitions
  • ✅ App-like Feeling
  • ✅ State bleibt erhalten
  • ✅ Bookmarkable URLs

Router Setup

Option 1: Bei ng new (Empfohlen)

ng new my-app
? Would you like to add Angular routing? (y/N) y  # ✅ JA!

Angular erstellt automatisch:

  • app-routing.module.ts - Router Konfiguration
  • RouterModule Import in app.module.ts
  • <router-outlet> in app.component.html

Option 2: Nachträglich hinzufügen

ng generate module app-routing --flat --module=app

app-routing.module.ts manuell erstellen:

import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';

const routes: Routes = [];  // Routes kommen hier rein

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

In app.module.ts importieren:

import { AppRoutingModule } from './app-routing.module';

@NgModule({
  imports: [
    BrowserModule,
    AppRoutingModule  // ✅ Router aktiviert
  ],
  // ...
})
export class AppModule { }

In app.component.html Router Outlet hinzufügen:

<nav>
  <!-- Navigation Links -->
</nav>

<router-outlet></router-outlet>  <!-- ✅ Views werden hier geladen -->

<router-outlet> ist der Platzhalter für deine Seiten!

Erste Routes definieren

Komponenten erstellen

ng generate component pages/home
ng generate component pages/about
ng generate component pages/contact

Oder kurz:

ng g c pages/home
ng g c pages/about
ng g c pages/contact

Routes konfigurieren

app-routing.module.ts:

import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { HomeComponent } from './pages/home/home.component';
import { AboutComponent } from './pages/about/about.component';
import { ContactComponent } from './pages/contact/contact.component';

const routes: Routes = [
  { path: '', component: HomeComponent },        // / (Root)
  { path: 'about', component: AboutComponent },  // /about
  { path: 'contact', component: ContactComponent } // /contact
];

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

Erklärung:

  • path: '' - Root Route (Homepage)
  • path: 'about' - URL ist /about
  • component: AboutComponent - Zeige diese Komponente

URLs:

  • http://localhost:4200/ → HomeComponent
  • http://localhost:4200/about → AboutComponent
  • http://localhost:4200/contact → ContactComponent

Navigation mit routerLink

HTML Navigation

app.component.html:

<nav class="navbar">
  <a routerLink="/" routerLinkActive="active" [routerLinkActiveOptions]="{exact: true}">
    Home
  </a>
  <a routerLink="/about" routerLinkActive="active">
    About
  </a>
  <a routerLink="/contact" routerLinkActive="active">
    Contact
  </a>
</nav>

<router-outlet></router-outlet>

Erklärung:

  • routerLink="/" - Navigiert zu dieser Route (NICHT href!)
  • routerLinkActive="active" - CSS Klasse wenn Route aktiv
  • [routerLinkActiveOptions]="{exact: true}" - Exact Match für Root

Styling:

/* app.component.css */
.navbar {
  display: flex;
  gap: 1rem;
  padding: 1rem;
  background: #1f2937;
}

.navbar a {
  color: #9ca3af;
  text-decoration: none;
  padding: 0.5rem 1rem;
  border-radius: 4px;
  transition: all 0.2s;
}

.navbar a:hover {
  color: white;
  background: #374151;
}

.navbar a.active {
  color: white;
  background: #3b82f6;
}

✅ Jetzt hast du funktionierende Navigation!

Tipps & Tricks

routerLink vs href

NICHT nutzen:

<!-- ❌ BAD: Normale Links -->
<a href="/about">About</a>

Problem: Page Reload! App-State geht verloren!

Nutzen:

<!-- ✅ GOOD: Router Links -->
<a routerLink="/about">About</a>

Vorteile:

  • Kein Page Reload
  • State bleibt erhalten
  • Schneller!

routerLinkActive Tricks

Exact Match für Root:

<a
  routerLink="/"
  routerLinkActive="active"
  [routerLinkActiveOptions]="{exact: true}"
>
  Home
</a>

Ohne exact: true wäre "/" IMMER active (weil jede Route mit "/" startet)!

Multiple CSS Classes:

<a
  routerLink="/about"
  routerLinkActive="active highlight"
>
  About
</a>

CSS Class auf Parent Element:

<li routerLinkActive="active-parent">
  <a routerLink="/about">About</a>
</li>

Programmatische Navigation

Im TypeScript Code navigieren

home.component.ts:

import { Component } from '@angular/core';
import { Router } from '@angular/router';

@Component({
  selector: 'app-home',
  template: `
    <div class="home">
      <h1>Willkommen auf der Homepage!</h1>
      <button (click)="goToAbout()">Über uns</button>
      <button (click)="goToContact()">Kontakt</button>
    </div>
  `
})
export class HomeComponent {

  // ✅ Router injizieren
  constructor(private router: Router) {}

  goToAbout() {
    // Navigiere zu /about
    this.router.navigate(['/about']);
  }

  goToContact() {
    this.router.navigateByUrl('/contact');
  }
}

Zwei Methoden:

  1. navigate(['/path']) - Array-basiert
  2. navigateByUrl('/path') - String-basiert

Nutze navigate() für komplexe Navigation mit Parameters!

Navigation mit Rückgabe-Wert

async navigateToAbout() {
  const success = await this.router.navigate(['/about']);

  if (success) {
    console.log('Navigation erfolgreich!');
  } else {
    console.log('Navigation fehlgeschlagen!');
  }
}

Route Parameters

Dynamic Routes

Problem: Du willst /user/1, /user/2, /user/123 unterstützen.

Lösung: Route Parameters!

app-routing.module.ts:

const routes: Routes = [
  { path: '', component: HomeComponent },
  { path: 'user/:id', component: UserDetailComponent }  // :id = Parameter
];

:id ist ein Platzhalter für dynamische Werte!

Parameter auslesen

user-detail.component.ts:

import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';

@Component({
  selector: 'app-user-detail',
  template: `
    <div class="user-detail">
      <h1>User Detail</h1>
      <p>User ID: {{ userId }}</p>
      <button (click)="goBack()">Zurück</button>
    </div>
  `
})
export class UserDetailComponent implements OnInit {
  userId: string | null = null;

  // ✅ ActivatedRoute injizieren
  constructor(
    private route: ActivatedRoute,
    private router: Router
  ) {}

  ngOnInit() {
    // Methode 1: Snapshot (für statische Params)
    this.userId = this.route.snapshot.paramMap.get('id');

    // Methode 2: Observable (für dynamische Params)
    this.route.paramMap.subscribe(params => {
      this.userId = params.get('id');
      console.log('User ID:', this.userId);
    });
  }

  goBack() {
    this.router.navigate(['/']);
  }
}

Navigation zu User Detail:

<!-- HTML -->
<a routerLink="/user/123">User 123</a>
<a [routerLink]="['/user', userId]">User Detail</a>

<!-- TypeScript -->
this.router.navigate(['/user', 123]);

Multiple Route Parameters

const routes: Routes = [
  { path: 'product/:category/:id', component: ProductComponent }
];

URL: /product/electronics/42

Auslesen:

ngOnInit() {
  const category = this.route.snapshot.paramMap.get('category'); // 'electronics'
  const id = this.route.snapshot.paramMap.get('id');             // '42'
}

Query Parameters

Query Parameters sind zusätzliche Daten in der URL: ?filter=active&sort=name

Query Params setzen

HTML:

<a
  routerLink="/products"
  [queryParams]="{filter: 'active', sort: 'name'}"
>
  Active Products
</a>

TypeScript:

this.router.navigate(['/products'], {
  queryParams: { filter: 'active', sort: 'name' }
});

URL: /products?filter=active&sort=name

Query Params auslesen

export class ProductListComponent implements OnInit {

  constructor(private route: ActivatedRoute) {}

  ngOnInit() {
    // Snapshot
    const filter = this.route.snapshot.queryParamMap.get('filter');
    const sort = this.route.snapshot.queryParamMap.get('sort');

    // Observable
    this.route.queryParamMap.subscribe(params => {
      const filter = params.get('filter');
      const sort = params.get('sort');
      console.log('Filter:', filter, 'Sort:', sort);
    });
  }
}

Häufige Fehler

Fehler 1: snapshot vs Observable

Problem:

ngOnInit() {
  // ❌ Snapshot updated nicht wenn Parameter ändern!
  this.userId = this.route.snapshot.paramMap.get('id');
}

Szenario: Navigation von /user/1 zu /user/2 ohne Komponente zu verlassen.

Resultat: userId bleibt 1! ❌

Lösung: Observable nutzen

ngOnInit() {
  // ✅ Observable reagiert auf Änderungen!
  this.route.paramMap.subscribe(params => {
    this.userId = params.get('id');
    this.loadUserData();  // Neu laden!
  });
}

Faustregel:

  • Snapshot: Wenn Parameter sich nie ändert (Komponente wird neu erstellt)
  • Observable: Wenn Navigation innerhalb der Komponente möglich ist

Fehler 2: href statt routerLink

Problem:

<a href="/about">About</a>  <!-- ❌ Page Reload! -->

Lösung:

<a routerLink="/about">About</a>  <!-- ✅ Kein Reload -->

Fehler 3: Router Outlet vergessen

Problem:

<!-- app.component.html -->
<nav>...</nav>
<!-- ❌ Kein <router-outlet>! -->

Resultat: Seiten werden nicht angezeigt!

Lösung:

<nav>...</nav>
<router-outlet></router-outlet>  <!-- ✅ Outlet hinzufügen! -->

Wildcard Routes & 404-Seite

404 Not Found Page

Komponente erstellen:

ng generate component pages/not-found

not-found.component.ts:

import { Component } from '@angular/core';
import { Router } from '@angular/router';

@Component({
  selector: 'app-not-found',
  template: `
    <div class="not-found">
      <h1>404 - Seite nicht gefunden</h1>
      <p>Die gesuchte Seite existiert nicht.</p>
      <button (click)="goHome()">Zur Homepage</button>
    </div>
  `,
  styles: [`
    .not-found {
      text-align: center;
      padding: 3rem;
    }
    h1 {
      font-size: 3rem;
      color: #ef4444;
    }
    button {
      padding: 0.75rem 1.5rem;
      background: #3b82f6;
      color: white;
      border: none;
      border-radius: 8px;
      cursor: pointer;
      font-size: 1rem;
    }
  `]
})
export class NotFoundComponent {
  constructor(private router: Router) {}

  goHome() {
    this.router.navigate(['/']);
  }
}

Route hinzufügen:

const routes: Routes = [
  { path: '', component: HomeComponent },
  { path: 'about', component: AboutComponent },
  { path: 'contact', component: ContactComponent },

  // ⭐ Wildcard Route MUSS ZULETZT kommen!
  { path: '**', component: NotFoundComponent }
];

** matched ALLE unbekannten Routes!

⚠️ Wichtig: Wildcard Route IMMER ALS LETZTES!

Redirect Routes

Homepage Redirect:

const routes: Routes = [
  { path: '', redirectTo: '/home', pathMatch: 'full' },
  { path: 'home', component: HomeComponent },
  // ...
];

Legacy Route Redirect:

const routes: Routes = [
  { path: 'old-about', redirectTo: '/about', pathMatch: 'full' },
  { path: 'about', component: AboutComponent }
];

pathMatch: 'full' bedeutet: Komplette URL muss matchen!

Nested Routes (Verschachtelte Routen)

Beispiel: Dashboard mit Sub-Pages

/dashboard          → Dashboard Overview
/dashboard/stats    → Dashboard Stats
/dashboard/profile  → Dashboard Profile

Komponenten erstellen:

ng g c pages/dashboard
ng g c pages/dashboard/stats
ng g c pages/dashboard/profile

Routes:

const routes: Routes = [
  { path: '', component: HomeComponent },
  {
    path: 'dashboard',
    component: DashboardComponent,
    children: [  // ⭐ Verschachtelte Routes
      { path: '', redirectTo: 'stats', pathMatch: 'full' },
      { path: 'stats', component: StatsComponent },
      { path: 'profile', component: ProfileComponent }
    ]
  }
];

dashboard.component.html:

<div class="dashboard">
  <h1>Dashboard</h1>

  <nav class="sub-nav">
    <a routerLink="stats" routerLinkActive="active">Stats</a>
    <a routerLink="profile" routerLinkActive="active">Profile</a>
  </nav>

  <!-- ⭐ Nested Router Outlet für Children -->
  <router-outlet></router-outlet>
</div>

Wichtig: Child-Komponenten brauchen eigenes <router-outlet>!

Route Guards

Guards schützen Routes vor unerlaubtem Zugriff.

Beispiel: User muss eingeloggt sein um Dashboard zu sehen.

Auth Guard erstellen

ng generate guard guards/auth

auth.guard.ts:

import { Injectable } from '@angular/core';
import { CanActivate, Router, UrlTree } from '@angular/router';
import { AuthService } from '../services/auth.service';

@Injectable({
  providedIn: 'root'
})
export class AuthGuard implements CanActivate {

  constructor(
    private authService: AuthService,
    private router: Router
  ) {}

  canActivate(): boolean | UrlTree {
    const isLoggedIn = this.authService.isLoggedIn();

    if (isLoggedIn) {
      return true;  // ✅ Zugriff erlaubt
    } else {
      // ❌ Redirect zu Login
      return this.router.createUrlTree(['/login']);
    }
  }
}

Guard auf Route anwenden:

const routes: Routes = [
  { path: '', component: HomeComponent },
  { path: 'login', component: LoginComponent },
  {
    path: 'dashboard',
    component: DashboardComponent,
    canActivate: [AuthGuard]  // ⭐ Guard aktiviert!
  }
];

Wenn User nicht eingeloggt:

  • Versuch zu navigieren nach /dashboard
  • Guard checkt: isLoggedIn() = false
  • Redirect zu /login

AuthService (Simple Variante)

import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root'
})
export class AuthService {
  private loggedIn = false;

  login(username: string, password: string): boolean {
    // In Realität: API Call
    if (username === 'admin' && password === 'password') {
      this.loggedIn = true;
      localStorage.setItem('isLoggedIn', 'true');
      return true;
    }
    return false;
  }

  logout(): void {
    this.loggedIn = false;
    localStorage.removeItem('isLoggedIn');
  }

  isLoggedIn(): boolean {
    return this.loggedIn || localStorage.getItem('isLoggedIn') === 'true';
  }
}

Andere Guard Typen

CanDeactivate: Verhindert Verlassen der Route (unsaved changes)

export class UnsavedChangesGuard implements CanDeactivate<ComponentWithForm> {
  canDeactivate(component: ComponentWithForm): boolean {
    if (component.hasUnsavedChanges()) {
      return confirm('Du hast ungespeicherte Änderungen. Wirklich verlassen?');
    }
    return true;
  }
}

CanLoad: Verhindert Lazy Loading (später mehr)

🔍

Debugging & Troubleshooting

Route wird nicht gefunden

Problem: Komponente wird nicht angezeigt

Check:

  1. Ist Route in app-routing.module.ts definiert?
  2. Ist <router-outlet> im Template?
  3. Ist AppRoutingModule in app.module.ts importiert?
  4. Ist Pfad korrekt geschrieben? (/about nicht /abuot)

Console prüfen:

// In Component
constructor(private router: Router) {
  console.log('Current URL:', this.router.url);
}

routerLinkActive funktioniert nicht

Problem: CSS Klasse wird nicht gesetzt

Check:

  • Für Root (/) brauchst du [routerLinkActiveOptions]="{exact: true}"
  • CSS Klasse existiert im Stylesheet?

Testen:

<a
  routerLink="/"
  routerLinkActive="active"
  [routerLinkActiveOptions]="{exact: true}"
  class="test"
>
  Home
</a>

Guard blockiert nicht

Problem: Guard lässt alles durch

Check:

  1. Ist Guard in Route konfiguriert? (canActivate: [AuthGuard])
  2. Returned Guard true oder false?
  3. Ist Guard @Injectable({ providedIn: 'root' })?

Debuggen:

canActivate(): boolean {
  const isLoggedIn = this.authService.isLoggedIn();
  console.log('Guard check:', isLoggedIn);  // ✅ Debug
  return isLoggedIn;
}

Lazy Loading (Performance Boost!)

Lazy Loading lädt Modules/Routes nur wenn gebraucht!

Problem ohne Lazy Loading:

User lädt App
→ ALLE Komponenten werden geladen (100+ KB)
→ Auch Komponenten die User nie sieht!
→ Langsamer Initial Load ❌

Mit Lazy Loading:

User lädt App
→ Nur Homepage wird geladen (20 KB)
→ User navigiert zu /admin
→ JETZT wird Admin-Module geladen (30 KB)
→ Schneller Initial Load! ✅

Feature Module erstellen

ng generate module features/admin --route admin --module app-routing

Angular erstellt automatisch:

  • admin.module.ts - Feature Module
  • admin-routing.module.ts - Routes für Admin
  • admin.component.ts - Admin Komponente
  • Lazy Load Route in app-routing.module.ts

app-routing.module.ts:

const routes: Routes = [
  { path: '', component: HomeComponent },
  {
    path: 'admin',
    loadChildren: () => import('./features/admin/admin.module').then(m => m.AdminModule)
  }
];

loadChildren lädt Module lazy!

Vorteile:

  • ✅ Schnellerer Initial Load
  • ✅ Kleinere Bundle Size
  • ✅ Code Splitting
  • ✅ Bessere Performance

Tipps & Tricks

Router Best Practices

1. Nutze routerLink, nicht href:

<!-- ✅ GOOD -->
<a routerLink="/about">About</a>

<!-- ❌ BAD -->
<a href="/about">About</a>

2. Relative vs Absolute Paths:

<!-- Absolute (from Root) -->
<a routerLink="/dashboard/stats">Stats</a>

<!-- Relative (from current route) -->
<a routerLink="stats">Stats</a>
<a routerLink="../profile">Profile</a>

3. Array Syntax für komplexe Pfade:

// ✅ GOOD: Type-safe
this.router.navigate(['/user', userId, 'edit']);

// ⚠️ OK: String concat
this.router.navigateByUrl(`/user/${userId}/edit`);

4. Query Params behalten:

this.router.navigate(['/products'], {
  queryParamsHandling: 'preserve'  // ✅ Params bleiben erhalten
});

5. Fragment für Anchor Links:

this.router.navigate(['/about'], {
  fragment: 'team'  // → /about#team
});

Navigation Testen

Prüfe ob Navigation funktioniert hat:

const success = await this.router.navigate(['/about']);
console.log('Navigation success:', success);

Aktuelle Route herausfinden:

constructor(private router: Router) {
  console.log('Current URL:', this.router.url);

  this.router.events.subscribe(event => {
    if (event instanceof NavigationEnd) {
      console.log('Navigated to:', event.url);
    }
  });
}

Komplettes Beispiel: Blog App

Routes:

const routes: Routes = [
  { path: '', component: HomeComponent },
  { path: 'blog', component: BlogListComponent },
  { path: 'blog/:slug', component: BlogPostComponent },
  { path: 'about', component: AboutComponent },
  { path: 'contact', component: ContactComponent },
  { path: '**', component: NotFoundComponent }
];

blog-list.component.ts:

import { Component } from '@angular/core';

interface BlogPost {
  slug: string;
  title: string;
  excerpt: string;
}

@Component({
  selector: 'app-blog-list',
  template: `
    <div class="blog-list">
      <h1>Blog Posts</h1>

      <div class="posts">
        <article *ngFor="let post of posts" class="post-card">
          <h2>{{ post.title }}</h2>
          <p>{{ post.excerpt }}</p>
          <a [routerLink]="['/blog', post.slug]" class="read-more">
            Weiterlesen →
          </a>
        </article>
      </div>
    </div>
  `,
  styles: [`
    .post-card {
      padding: 1.5rem;
      border: 1px solid #e5e7eb;
      border-radius: 8px;
      margin-bottom: 1rem;
    }
    .read-more {
      color: #3b82f6;
      text-decoration: none;
      font-weight: 600;
    }
  `]
})
export class BlogListComponent {
  posts: BlogPost[] = [
    { slug: 'angular-basics', title: 'Angular Basics', excerpt: 'Lerne Angular Grundlagen...' },
    { slug: 'angular-routing', title: 'Angular Routing', excerpt: 'Navigation in Angular...' },
    { slug: 'angular-forms', title: 'Angular Forms', excerpt: 'Forms in Angular...' }
  ];
}

blog-post.component.ts:

import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';

interface BlogPost {
  slug: string;
  title: string;
  content: string;
  date: string;
}

@Component({
  selector: 'app-blog-post',
  template: `
    <article class="blog-post" *ngIf="post; else notFound">
      <button (click)="goBack()" class="back-btn">← Zurück</button>

      <h1>{{ post.title }}</h1>
      <p class="date">{{ post.date }}</p>
      <div class="content">
        {{ post.content }}
      </div>

      <div class="navigation">
        <button (click)="previousPost()" [disabled]="!hasPrevious()">
          ← Vorheriger Post
        </button>
        <button (click)="nextPost()" [disabled]="!hasNext()">
          Nächster Post →
        </button>
      </div>
    </article>

    <ng-template #notFound>
      <div class="not-found">
        <h1>Post nicht gefunden</h1>
        <button (click)="goBack()">Zurück zur Blog-Liste</button>
      </div>
    </ng-template>
  `
})
export class BlogPostComponent implements OnInit {
  post: BlogPost | null = null;
  allPosts: BlogPost[] = [
    { slug: 'angular-basics', title: 'Angular Basics', content: 'Content...', date: '2025-01-01' },
    { slug: 'angular-routing', title: 'Angular Routing', content: 'Content...', date: '2025-01-15' },
    { slug: 'angular-forms', title: 'Angular Forms', content: 'Content...', date: '2025-01-30' }
  ];

  constructor(
    private route: ActivatedRoute,
    private router: Router
  ) {}

  ngOnInit() {
    this.route.paramMap.subscribe(params => {
      const slug = params.get('slug');
      this.loadPost(slug);
    });
  }

  loadPost(slug: string | null) {
    if (!slug) return;
    this.post = this.allPosts.find(p => p.slug === slug) || null;
  }

  goBack() {
    this.router.navigate(['/blog']);
  }

  hasPrevious(): boolean {
    if (!this.post) return false;
    const index = this.allPosts.findIndex(p => p.slug === this.post!.slug);
    return index > 0;
  }

  hasNext(): boolean {
    if (!this.post) return false;
    const index = this.allPosts.findIndex(p => p.slug === this.post!.slug);
    return index < this.allPosts.length - 1;
  }

  previousPost() {
    if (!this.post) return;
    const index = this.allPosts.findIndex(p => p.slug === this.post!.slug);
    if (index > 0) {
      this.router.navigate(['/blog', this.allPosts[index - 1].slug]);
    }
  }

  nextPost() {
    if (!this.post) return;
    const index = this.allPosts.findIndex(p => p.slug === this.post!.slug);
    if (index < this.allPosts.length - 1) {
      this.router.navigate(['/blog', this.allPosts[index + 1].slug]);
    }
  }
}
🎯

Zusammenfassung

Du hast gelernt:

  • Angular Router ermöglicht Navigation ohne Page Reloads
  • ✅ Routes definieren mit { path: 'about', component: AboutComponent }
  • ✅ Navigation mit routerLink (HTML) und router.navigate() (TS)
  • <router-outlet> ist Platzhalter für Views
  • Route Parameters: :id für dynamische Routes
  • Query Parameters: ?filter=active&sort=name
  • routerLinkActive für active Link Styling
  • Wildcard Routes (**) für 404-Seiten
  • Guards schützen Routes (z.B. Auth)
  • Lazy Loading für bessere Performance

Key Takeaways:

  • routerLink statt href
  • ActivatedRoute für Parameter
  • Observable für dynamische Parameter
  • Guards für Authorization
  • Wildcard Route ZULETZT

Router Setup Cheatsheet:

// 1. Routes definieren
const routes: Routes = [
  { path: '', component: HomeComponent },
  { path: 'user/:id', component: UserComponent },
  { path: '**', component: NotFoundComponent }
];

// 2. HTML Navigation
<a routerLink="/about" routerLinkActive="active">About</a>

// 3. TypeScript Navigation
this.router.navigate(['/user', userId]);

// 4. Parameter auslesen
this.route.paramMap.subscribe(params => {
  const id = params.get('id');
});

Routing macht deine App zu einer echten SPA! 🎯

Quiz

📝 Quiz

Was macht <router-outlet>?

📝 Quiz

Wie navigierst du programmatisch zu /about?

📝 Quiz

Wofür nutzt man Route Guards?

Übungen

Übung 1: Multi-Page Portfolio

Erstelle eine Portfolio-Website mit:

  • Homepage (/)
  • About Page (/about)
  • Projects Page (/projects)
  • Contact Page (/contact)
  • 404 Page

Bonus: Active Link Styling mit routerLinkActive

Übung 2: Product Detail Page

Erstelle:

  • Product List (/products) - Zeigt alle Produkte
  • Product Detail (/products/:id) - Zeigt ein Produkt
  • Navigation zwischen Produkten (Previous/Next Buttons)

Daten:

products = [
  { id: 1, name: 'Laptop', price: 999 },
  { id: 2, name: 'Phone', price: 699 },
  { id: 3, name: 'Tablet', price: 499 }
];

Übung 3: Protected Dashboard

Erstelle:

  • Login Page (/login)
  • Dashboard (/dashboard) - Protected mit AuthGuard
  • Logout Button im Dashboard

Auth Logic:

  • Login mit username: 'admin', password: 'test'
  • Nach Login redirect zu Dashboard
  • Ohne Login kein Zugriff auf Dashboard (Redirect zu Login)

Nächste Schritte

Im nächsten Artikel:

  • Reactive Forms
  • Form Validation
  • Custom Validators
  • Dynamic Forms
  • Form Arrays

➡️ Weiter zu: Angular Reactive Forms

Routing gemeistert! Zeit für Forms! 🚀

AngularLektion 7 von 10
70% abgeschlossen
Lektion abgeschlossen!

Gut gemacht! 🎉

Du hast "Angular Routing & Navigation - Multi-Page Apps erstellen" abgeschlossen

Artikel bewerten

0.0 (0 Bewertungen)

Bitte einloggen um zu bewerten