Angular 20 is a robust framework for building single-page applications (SPAs), and routing is the backbone of navigating between views seamlessly. Whether you’re creating a user dashboard, an admin panel, or a dynamic details page, the Angular Router empowers you to map URLs to components, pass data, and handle navigation events. As a beginner, mastering routing is a crucial step after learning components, templates, and directives. In this guide, we’ll explore Angular routing in depth, from configuring routes to building a hands-on project that navigates between User and Admin dashboards and includes a User Details page with a dynamic ID. We’ll also troubleshoot common errors like TS2305 and integrate concepts like directives and pipes from previous lessons.
This tutorial assumes you have a basic Angular 20 project (created with ng new) and familiarity with components. Let’s embark on this journey to master Angular routing!
IntroductionRouting in Angular allows users to navigate between different views (e.g., dashboards, profiles) without reloading the entire page, creating a smooth SPA experience. The Angular Router provides tools for defining routes, passing parameters, handling nested navigation, and tracking events. In Angular 20, the shift to standalone components simplifies routing by eliminating NgModule dependencies in many cases.In this guide, we’ll cover:
Introduction to Angular RouterThe Angular Router is a powerful module that manages navigation in Angular SPAs. It maps URLs to components, allowing users to switch views dynamically. Key features include:
Configuring app.routes.tsIn Angular 20, routes are defined in a standalone app.routes.ts file and provided to the application via provideRouter. Let’s set up routes for the User and Admin components.Step 1: Create app.routes.tsCreate a file named app.routes.ts in src/app/:Explanation:Explanation:Explanation:
Navigation Using routerLinkThe routerLink directive enables declarative navigation in templates, replacing traditional <a href> to prevent page reloads. It’s paired with routerLinkActive to style active routes.Step 1: Update app.component.htmlAdd a navigation bar:Explanation:Visit http://localhost:4200:
Wildcard Routes (**) & RedirectsWildcard routes handle undefined paths (e.g., 404 errors), while redirects manage default or invalid routes.Step 1: Create NotFoundComponentExplanation:Explanation:
Route ParametersRoute parameters enable dynamic URLs (e.g., /user/:id) to display specific data, such as a user’s profile.Step 1: Create UserDetailsComponentExplanation:Step 3: Update UserComponentAdd links to user details:Explanation:
Query ParametersQuery parameters (e.g., ?search=john) pass optional data in the URL, useful for filters or search queries.Step 1: Enhance UserComponentThe UserComponent above already includes query parameter handling. Let’s ensure it works:Explanation:
Child Routes (Nested Routing)Child routes enable nested navigation, rendering components within a parent component’s router-outlet. Let’s add child routes for the Admin panel (Dashboard and Settings).Step 1: Create Child ComponentsStep 2: Update app.routes.tsAdd child routes:Step 3: Update AdminComponentIntegrate child routes with the existing users list:Step 4: Update FilterByRolePipeStep 5: Test Child RoutesNavigate to /admin/dashboard and /admin/settings to see the child components rendered within the AdminComponent’s router-outlet.
Router EventsRouter events allow you to track navigation actions, such as NavigationStart and NavigationEnd, for tasks like analytics or loading indicators.Step 1: Add Router Events to AppComponentExplanation:
Hands-On Project: Navigate Between User & Admin Dashboards with User Details PageLet’s build a project that integrates all the above concepts, reusing the User and Admin components and adding a dynamic User Details page.Step 1: Set Up the ProjectStep 2: Configure All FilesUse the code provided above for:
Troubleshooting Common Routing ErrorsTS2305: Module '"./app/app"' has no exported member 'App'Cause: main.ts imports App instead of AppComponent.Fix:Steps:
Best Practices for Angular Routing
ConclusionAngular 20’s routing system is a powerful tool for building dynamic SPAs. You’ve learned how to configure routes, navigate with routerLink, handle parameters, create child routes, and track router events. The hands-on project brought these concepts together with User and Admin dashboards, a dynamic User Details page, and features like directives and pipes. Keep practicing to solidify your skills!What’s Next?
This tutorial assumes you have a basic Angular 20 project (created with ng new) and familiarity with components. Let’s embark on this journey to master Angular routing!
IntroductionRouting in Angular allows users to navigate between different views (e.g., dashboards, profiles) without reloading the entire page, creating a smooth SPA experience. The Angular Router provides tools for defining routes, passing parameters, handling nested navigation, and tracking events. In Angular 20, the shift to standalone components simplifies routing by eliminating NgModule dependencies in many cases.In this guide, we’ll cover:
- Configuring routes in app.routes.ts.
- Navigating with routerLink.
- Handling wildcard routes and redirects.
- Using route and query parameters.
- Creating nested (child) routes.
- Listening to router events.
- Building a hands-on project with User and Admin dashboards and a dynamic User Details page.
Introduction to Angular RouterThe Angular Router is a powerful module that manages navigation in Angular SPAs. It maps URLs to components, allowing users to switch views dynamically. Key features include:
- Declarative Navigation: Use routerLink in templates for clickable links.
- Dynamic Routes: Pass parameters like /user/:id for personalized views.
- Nested Routing: Support complex UIs with child routes.
- Event Handling: Track navigation events for analytics or UI feedback.
- Standalone Support: In Angular 20, routes work seamlessly with standalone components.
Configuring app.routes.tsIn Angular 20, routes are defined in a standalone app.routes.ts file and provided to the application via provideRouter. Let’s set up routes for the User and Admin components.Step 1: Create app.routes.tsCreate a file named app.routes.ts in src/app/:
typescript
// src/app/app.routes.ts
import { Routes } from '@angular/router';
import { UserComponent } from './components/user/user.component';
import { AdminComponent } from './components/admin/admin.component';
export const routes: Routes = [
{ path: 'user', component: UserComponent },
{ path: 'admin', component: AdminComponent },
{ path: '', redirectTo: '/user', pathMatch: 'full' }
];
- Routes: An array of route objects, each mapping a URL path to a component.
- path: 'user': Maps /user to UserComponent.
- path: '': Defines the default route, redirecting to /user.
- pathMatch: 'full': Ensures the redirect only triggers for an exact match of the empty path.
typescript
// src/main.ts
import { bootstrapApplication } from '@angular/platform-browser';
import { provideRouter } from '@angular/router';
import { AppComponent } from './app/app.component';
import { routes } from './app/app.routes';
bootstrapApplication(AppComponent, {
providers: [provideRouter(routes)]
}).catch(err => console.error(err));
- provideRouter(routes): Registers the routes with the Angular Router.
- bootstrapApplication: Starts the app with AppComponent as the root.
typescript
// src/app/app.component.ts
import { Component } from '@angular/core';
import { RouterOutlet } from '@angular/router';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
standalone: true,
imports: [RouterOutlet]
})
export class AppComponent {}
- RouterOutlet: A directive that acts as a placeholder where routed components are rendered.
- standalone: true: Indicates AppComponent doesn’t rely on an NgModule.
- imports: [RouterOutlet]: Imports the RouterOutlet directive.
Navigation Using routerLinkThe routerLink directive enables declarative navigation in templates, replacing traditional <a href> to prevent page reloads. It’s paired with routerLinkActive to style active routes.Step 1: Update app.component.htmlAdd a navigation bar:
typescript
// src/app/app.component.html
nav:
User Dashboard | Admin Panel
router-outlet
css
// src/app/app.component.css
nav { margin: 20px; }
a { margin-right: 10px; text-decoration: none; }
.active { font-weight: bold; color: #007bff; }
- routerLink="/user": Navigates to the /user route, rendering UserComponent.
- routerLinkActive="active": Applies the active CSS class when the route is active.
- router-outlet: Renders the component associated with the current route.
bash
ng serve
- Click “User Dashboard” to see UserComponent.
- Click “Admin Panel” to see AdminComponent.
- The default route (/) redirects to /user.
- The active link is styled in bold blue.
Wildcard Routes (**) & RedirectsWildcard routes handle undefined paths (e.g., 404 errors), while redirects manage default or invalid routes.Step 1: Create NotFoundComponent
bash
ng g component components/not-found
typescript
// src/app/components/not-found/not-found.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'app-not-found',
template: `
h2: 404 - Page Not Found
p: Go back to User Dashboard
`,
standalone: true,
imports: [RouterLink]
})
export class NotFoundComponent {}
- A simple component to display a 404 message with a link back to /user.
typescript
// src/app/app.routes.ts
import { Routes } from '@angular/router';
import { UserComponent } from './components/user/user.component';
import { AdminComponent } from './components/admin/admin.component';
import { NotFoundComponent } from './components/not-found/not-found.component';
export const routes: Routes = [
{ path: 'user', component: UserComponent },
{ path: 'admin', component: AdminComponent },
{ path: '', redirectTo: '/user', pathMatch: 'full' },
{ path: '**', component: NotFoundComponent }
];
- path: '**': Matches any undefined route, rendering NotFoundComponent.
- The redirect ('' to /user) ensures the default route is handled.
Route ParametersRoute parameters enable dynamic URLs (e.g., /user/:id) to display specific data, such as a user’s profile.Step 1: Create UserDetailsComponent
bash
ng g component components/user-details
typescript
// src/app/components/user-details/user-details.component.ts
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, RouterLink } from '@angular/router';
@Component({
selector: 'app-user-details',
template: `
h2: User Details
p: User ID: {{ userId }}
p: Go back to User Dashboard
`,
standalone: true,
imports: [RouterLink]
})
export class UserDetailsComponent implements OnInit {
userId: string | null = null;
constructor(private route: ActivatedRoute) {}
ngOnInit() {
this.route.paramMap.subscribe(params => {
this.userId = params.get('id');
});
}
}
- :id in the route path is a dynamic parameter.
- ActivatedRoute provides access to parameters via paramMap.
- subscribe ensures the component updates if the parameter changes (e.g., navigating between /user/1 and /user/2).
typescript
// src/app/app.routes.ts
import { UserDetailsComponent } from './components/user-details/user-details.component';
export const routes: Routes = [
{ path: 'user', component: UserComponent },
{ path: 'user/:id', component: UserDetailsComponent },
{ path: 'admin', component: AdminComponent },
{ path: '', redirectTo: '/user', pathMatch: 'full' },
{ path: '**', component: NotFoundComponent }
];
typescript
// src/app/components/user/user.component.ts
import { Component, OnInit } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { ActivatedRoute, Router, RouterLink } from '@angular/router';
@Component({
selector: 'app-user',
templateUrl: './user.component.html',
styleUrls: ['./user.component.css'],
standalone: true,
imports: [FormsModule, RouterLink]
})
export class UserComponent implements OnInit {
searchQuery = '';
users = [
{ id: 1, name: 'Alice' },
{ id: 2, name: 'Bob' }
];
constructor(private route: ActivatedRoute, private router: Router) {}
ngOnInit() {
this.route.queryParamMap.subscribe(params => {
this.searchQuery = params.get('search') || '';
});
}
updateQuery() {
this.router.navigate(['/user'], { queryParams: { search: this.searchQuery } });
}
}
typescript
// src/app/components/user/user.component.html
h2: User Dashboard
div:
label: Search users:
input: [(ngModel)]="searchQuery" placeholder="Search users"
button: (click)="updateQuery()": Search
p: Search Query: {{ searchQuery }}
ul:
li: *ngFor="let user of users":
a: routerLink="/user/{{ user.id }}": {{ user.name }}
- The users array simulates a data source.
- routerLink="/user/{{ user.id }}" navigates to /user/1, /user/2, etc.
- The search input uses query parameters (covered next).
Query ParametersQuery parameters (e.g., ?search=john) pass optional data in the URL, useful for filters or search queries.Step 1: Enhance UserComponentThe UserComponent above already includes query parameter handling. Let’s ensure it works:
typescript
// src/app/components/user/user.component.ts (already shown above)
- queryParamMap retrieves the search query parameter.
- Router.navigate updates the URL with the search query.
- The template displays the current searchQuery.
- Enter “john” in the search input and click “Search”.
- The URL updates to http://localhost:4200/user?search=john.
- The template reflects the query parameter.
Child Routes (Nested Routing)Child routes enable nested navigation, rendering components within a parent component’s router-outlet. Let’s add child routes for the Admin panel (Dashboard and Settings).Step 1: Create Child Components
bash
ng g component components/admin-dashboard
ng g component components/admin-settings
typescript
// src/app/components/admin-dashboard/admin-dashboard.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'app-admin-dashboard',
template: Juno
h3: Admin Dashboard
p: Welcome to the Admin Dashboard!
standalone: true
})
export class AdminDashboardComponent {}
typescript
// src/app/components/admin-settings/admin-settings.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'app-admin-settings',
template: `
h3: Admin Settings
p: Configure settings here.
`,
standalone: true
})
export class AdminSettingsComponent {}
typescript
// src/app/app.routes.ts
export const routes: Routes = [
{ path: 'user', component: UserComponent },
{ path: 'user/:id', component: UserDetailsComponent },
{
path: 'admin',
component: AdminComponent,
children: [
{ path: 'dashboard', component: AdminDashboardComponent },
{ path: 'settings', component: AdminSettingsComponent },
{ path: '', redirectTo: 'dashboard', pathMatch: 'full' }
]
},
{ path: '', redirectTo: '/user', pathMatch: 'full' },
{ path: '**', component: NotFoundComponent }
];
typescript
// src/app/components/admin/admin.component.ts
import { Component, OnInit, OnDestroy } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { RouterOutlet, RouterLink } from '@angular/router';
import { FilterByRolePipe } from '../../pipes/filter-by-role.pipe';
@Component({
selector: 'app-admin',
templateUrl: './admin.component.html',
styleUrls: ['./admin.component.css'],
standalone: true,
imports: [FormsModule, RouterOutlet, RouterLink, FilterByRolePipe]
})
export class AdminComponent implements OnInit, OnDestroy {
users = [
{ name: 'Alice', roleId: 1, role: 'admin' },
{ name: 'Bob', roleId: 2, role: 'user' },
{ name: 'Charlie', roleId: 1, role: 'admin' },
{ name: 'David', roleId: 2, role: 'user' }
];
filterRole = 'admin';
isHighlighted = false;
ngOnInit() {
console.log('AdminComponent: Initialized');
}
ngOnDestroy() {
console.log('AdminComponent: Destroyed');
}
toggleHighlight() {
this.isHighlighted = !this.isHighlighted;
}
setFilterRole(role: string) {
this.filterRole = role;
}
logSearch(value: string) {
console.log('Search:', value);
}
}
typescript
// src/app/components/admin/admin.component.html
h2: Admin Panel
nav:
a: routerLink="dashboard" routerLinkActive="active": Dashboard
a: routerLink="settings" routerLinkActive="active": Settings
router-outlet
h3: Admin Users List
div:
label: Filter by Role:
select: [(ngModel)]="filterRole" (change)="setFilterRole(filterRole)":
option: value="all": All
option: value="admin": Admin
option: value="user": User
button: (click)="toggleHighlight()": Toggle Highlight
ul:
li: *ngFor="let user of users | filterByRole:filterRole" [ngClass]="{'highlight': isHighlighted && user.roleId === 1}":
{{ user.name | uppercase }} ({{ user.role }})
input: #searchInput placeholder="Search users"
button: (click)="logSearch(searchInput.value)": Search
css
// src/app/components/admin/admin.component.css
ul { list-style-type: none; padding: 0; }
li { padding: 10px; margin: 5px 0; border: 1px solid #ccc; }
.highlight { background-color: #e0f7fa; }
nav { margin: 10px 0; }
a { margin-right: 10px; text-decoration: none; }
.active { font-weight: bold; color: #007bff; }
typescript
// src/app/pipes/filter-by-role.pipe.ts
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
name: 'filterByRole',
standalone: true
})
export class FilterByRolePipe implements PipeTransform {
transform(users: any[], role: string): any[] {
if (!users || role === 'all') return users;
return users.filter(user => user.role === role);
}
}
Router EventsRouter events allow you to track navigation actions, such as NavigationStart and NavigationEnd, for tasks like analytics or loading indicators.Step 1: Add Router Events to AppComponent
typescript
// src/app/app.component.ts
import { Component, OnInit } from '@angular/core';
import { Router, NavigationStart, NavigationEnd, RouterOutlet } from '@angular/router';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
standalone: true,
imports: [RouterOutlet]
})
export class AppComponent implements OnInit {
constructor(private router: Router) {}
ngOnInit() {
this.router.events.subscribe(event => {
if (event instanceof NavigationStart) {
console.log('Navigation started:', event.url);
} else if (event instanceof NavigationEnd) {
console.log('Navigation ended:', event.url);
}
});
}
}
- router.events emits events like NavigationStart and NavigationEnd.
- Use these for loading spinners, logging, or analytics.
Hands-On Project: Navigate Between User & Admin Dashboards with User Details PageLet’s build a project that integrates all the above concepts, reusing the User and Admin components and adding a dynamic User Details page.Step 1: Set Up the Project
bash
ng new angular-routing-demo
cd angular-routing-demo
ng g component components/user
ng g component components/admin
ng g component components/user-details
ng g component components/not-found
ng g component components/admin-dashboard
ng g component components/admin-settings
ng g pipe pipes/filter-by-role
- app.routes.ts
- main.ts
- app.component.ts
- user.component.ts
- user-details.component.ts
- admin.component.ts
- admin-dashboard.component.ts
- admin-settings.component.ts
- not-found.component.ts
- filter-by-role.pipe.ts
- Run ng serve and visit http://localhost:4200.
- Test navigation:
- /user: View the User Dashboard with a search input and user list.
- /user/1: View the User Details page for ID 1.
- /admin: View the Admin Panel with child routes.
- /admin/dashboard: View the Admin Dashboard.
- /admin/settings: View the Admin Settings.
- /invalid: View the 404 page.
- Test features:
- Filter the admin users list by role.
- Toggle highlighting with [ngClass].
- Use the search input with query parameters.
- Check console logs for lifecycle hooks and router events.
Troubleshooting Common Routing ErrorsTS2305: Module '"./app/app"' has no exported member 'App'Cause: main.ts imports App instead of AppComponent.Fix:
typescript
// src/main.ts
import { bootstrapApplication } from '@angular/platform-browser';
import { provideRouter } from '@angular/router';
import { AppComponent } from './app/app.component';
import { routes } from './app/app.routes';
bootstrapApplication(AppComponent, {
providers: [provideRouter(routes)]
}).catch(err => console.error(err));
- Verify app.component.ts exports AppComponent.
- Ensure the file path is correct (./app/app.component).
- Run ng serve to test.
- Add RouterOutlet to imports in app.component.ts.
- Ensure provideRouter(routes) is in main.ts.
- Double-check route paths and routerLink values.
- Ensure components are imported in app.routes.ts.
Best Practices for Angular Routing
- Lazy Loading: Load modules only when needed:typescript
{ path: 'admin', loadChildren: () => import('./admin/admin.module').then(m => m.AdminModule) }
- Route Guards: Restrict access (e.g., canActivate for admin routes).
- Clear URLs: Use consistent, descriptive paths (e.g., /user/profile).
- Performance: Use onSameUrlNavigation for dynamic route updates.
ConclusionAngular 20’s routing system is a powerful tool for building dynamic SPAs. You’ve learned how to configure routes, navigate with routerLink, handle parameters, create child routes, and track router events. The hands-on project brought these concepts together with User and Admin dashboards, a dynamic User Details page, and features like directives and pipes. Keep practicing to solidify your skills!What’s Next?
- Add form validation to the search input.
- Implement route guards for secure navigation.
- Explore lazy loading for performance.
- Share your project with the community!
No comments:
Post a Comment
Thanks for your valuable comment...........
Md. Mominul Islam