Our User Management Application now has a UserListComponent and a UserFormComponent. While we’ve temporarily placed them directly in AppComponent, a real-world application needs proper routing to navigate between different views. In this chapter, we’ll structure our application with routing, creating dedicated “pages” for user listing and user creation.
This will utilize Angular’s router and reinforce the use of standalone components within a routed application.
Step 1: Create Page Components for Routing
Instead of putting UserListComponent and UserFormComponent directly in AppComponent, we’ll create container “page” components that the router will render. This separation keeps concerns clean.
Generate
UsersPageComponent: This will be the main entry point for user management, hosting the user list and a navigation link to add users.ng generate component features/users/pages/users-page --standalone --skip-testsGenerate
AddUserPageComponent: This page will host ourUserFormComponent.ng generate component features/users/pages/add-user-page --standalone --skip-tests
Step 2: Implement UsersPageComponent
Open src/app/features/users/pages/users-page/users-page.component.ts:
// src/app/features/users/pages/users-page/users-page.component.ts
import { Component } from '@angular/core';
import { CommonModule } from '@angular/common';
import { RouterLink } from '@angular/router'; // For routerLink in template
import { UserListComponent } from '../../components/user-list/user-list.component'; // Import UserListComponent
@Component({
selector: 'app-users-page',
standalone: true,
imports: [CommonModule, RouterLink, UserListComponent], // Import RouterLink and UserListComponent
templateUrl: './users-page.component.html',
styleUrls: ['./users-page.component.css'],
})
export class UsersPageComponent {
// This component will primarily act as a container
}
Now, create src/app/features/users/pages/users-page/users-page.component.html:
<!-- src/app/features/users/pages/users-page/users-page.component.html -->
<div class="users-page-container">
<h2>User Management</h2>
<nav class="user-nav">
<a routerLink="/users/add" routerLinkActive="active" class="btn btn-add-user">Add New User</a>
</nav>
<app-user-list></app-user-list> <!-- Embed the UserListComponent -->
</div>
And src/app/features/users/pages/users-page/users-page.component.css:
/* src/app/features/users/pages/users-page/users-page.component.css */
.users-page-container {
max-width: 900px;
margin: 30px auto;
padding: 30px;
background-color: #ffffff;
border-radius: 12px;
box-shadow: 0 8px 20px rgba(0, 0, 0, 0.08);
font-family: Arial, sans-serif;
}
h2 {
text-align: center;
color: #2c3e50;
margin-bottom: 30px;
font-size: 2.2em;
}
.user-nav {
text-align: right;
margin-bottom: 25px;
}
.btn-add-user {
display: inline-block;
padding: 10px 20px;
background-color: #28a745; /* Green */
color: white;
text-decoration: none;
border-radius: 6px;
font-weight: bold;
transition: background-color 0.3s ease;
}
.btn-add-user:hover {
background-color: #218838;
}
.btn-add-user.active {
background-color: #1a7e30; /* Slightly darker green for active */
}
Step 3: Implement AddUserPageComponent
Open src/app/features/users/pages/add-user-page/add-user-page.component.ts:
// src/app/features/users/pages/add-user-page/add-user-page.component.ts
import { Component } from '@angular/core';
import { CommonModule } from '@angular/common';
import { UserFormComponent } from '../../components/user-form/user-form.component'; // Import UserFormComponent
import { RouterLink } from '@angular/router';
@Component({
selector: 'app-add-user-page',
standalone: true,
imports: [CommonModule, UserFormComponent, RouterLink], // Import UserFormComponent and RouterLink
templateUrl: './add-user-page.component.html',
styleUrls: ['./add-user-page.component.css'],
})
export class AddUserPageComponent {
// This component will primarily host the user form
}
Now, create src/app/features/users/pages/add-user-page/add-user-page.component.html:
<!-- src/app/features/users/pages/add-user-page/add-user-page.component.html -->
<div class="add-user-page-container">
<h2>Create New User</h2>
<nav class="add-user-nav">
<a routerLink="/users" class="btn btn-back">← Back to Users</a>
</nav>
<app-user-form></app-user-form> <!-- Embed the UserFormComponent -->
</div>
And src/app/features/users/pages/add-user-page/add-user-page.component.css:
/* src/app/features/users/pages/add-user-page/add-user-page.component.css */
.add-user-page-container {
max-width: 600px;
margin: 30px auto;
padding: 30px;
background-color: #ffffff;
border-radius: 12px;
box-shadow: 0 8px 20px rgba(0, 0, 0, 0.08);
font-family: Arial, sans-serif;
}
h2 {
text-align: center;
color: #2c3e50;
margin-bottom: 30px;
font-size: 2.2em;
}
.add-user-nav {
margin-bottom: 25px;
}
.btn-back {
display: inline-block;
padding: 8px 15px;
background-color: #6c757d; /* Grey */
color: white;
text-decoration: none;
border-radius: 6px;
font-weight: normal;
transition: background-color 0.3s ease;
}
.btn-back:hover {
background-color: #5a6268;
}
Step 4: Configure Application Routes
Now, we need to define the routes in src/app/app.routes.ts to link our pages.
Open src/app/app.routes.ts and modify it:
// src/app/app.routes.ts
import { Routes } from '@angular/router';
import { UsersPageComponent } from './features/users/pages/users-page/users-page.component';
import { AddUserPageComponent } from './features/users/pages/add-user-page/add-user-page.component';
export const routes: Routes = [
{
path: '', redirectTo: 'users', pathMatch: 'full' // Redirect empty path to /users
},
{
path: 'users',
component: UsersPageComponent, // Main users page
},
{
path: 'users/add',
component: AddUserPageComponent, // Page to add new users
},
{
path: '**', redirectTo: 'users' // Wildcard route for any unknown paths
}
];
Step 5: Update AppComponent for Routing
Finally, update src/app/app.component.ts to remove the direct component embeds and instead use <router-outlet>. We’ll also add a basic application navigation.
// src/app/app.component.ts
import { Component } from '@angular/core';
import { CommonModule } from '@angular/common';
import { RouterOutlet, RouterLink, RouterLinkActive } from '@angular/router'; // Import RouterLink and RouterLinkActive
@Component({
selector: 'app-root',
standalone: true,
imports: [CommonModule, RouterOutlet, RouterLink, RouterLinkActive], // Add RouterLink, RouterLinkActive
template: `
<header class="app-header">
<nav class="main-nav">
<a routerLink="/users" routerLinkActive="active" [routerLinkActiveOptions]="{exact: true}">User List</a>
<a routerLink="/users/add" routerLinkActive="active">Add User</a>
</nav>
<h1>User Management Dashboard</h1>
</header>
<main>
<router-outlet></router-outlet> <!-- This is where routed components will be rendered -->
</main>
`,
styles: [`
.app-header {
background-color: #2c3e50; /* Dark blue-grey */
color: white;
padding: 15px 20px;
text-align: center;
box-shadow: 0 3px 8px rgba(0,0,0,0.15);
}
.main-nav {
margin-bottom: 15px;
display: flex;
justify-content: center;
gap: 20px;
}
.main-nav a {
color: #bbccdd;
text-decoration: none;
font-weight: bold;
padding: 8px 15px;
border-radius: 5px;
transition: background-color 0.3s ease, color 0.3s ease;
}
.main-nav a:hover {
background-color: rgba(255, 255, 255, 0.1);
color: white;
}
.main-nav a.active {
background-color: #007bff; /* Primary blue for active */
color: white;
}
h1 {
margin: 0;
font-size: 2.2em;
}
main {
padding: 20px;
background-color: #f8f9fa;
min-height: calc(100vh - 100px); /* Adjust based on header height */
}
`]
})
export class AppComponent {
title = 'user-management-app';
}
Step 6: Run and Test the Application
Ensure your json-server is running in one terminal:
npm run serve:json-api
And your Angular app in another:
ng serve
Open your browser to http://localhost:4200.
- You should be redirected to
/usersand see the user list. - Click the “Add New User” link. It should navigate to
/users/addand display theUserFormComponent. - Click the “← Back to Users” link. It should take you back to the user list.
- Try adding a new user from the form. It should appear in the list after successful submission and return to the user list page (if you add
this.router.navigate(['/users']);after the user is added).
Enhancement (Mini-Challenge): Navigate back to user list after adding user
In src/app/features/users/components/user-form/user-form.component.ts, after a user is successfully added (inside the next callback of the addUser subscription), use the Router to navigate back to the /users page.
// src/app/features/users/components/user-form/user-form.component.ts (snippet)
import { Router } from '@angular/router'; // Don't forget to import Router
export class UserFormComponent {
private userService = inject(UserService);
private router = inject(Router); // Inject the Router
// ... (rest of the component)
onSubmit(): void {
if (this.userForm.valid()) {
const newUser: NewUser = this.userForm.value();
// ...
this.userService.addUser(newUser)
.pipe(takeUntil(this.destroy$))
.subscribe({
next: (addedUser) => {
// ...
this.router.navigate(['/users']); // Navigate back to the user list
},
error: (err) => { /* ... */ }
});
} else { /* ... */ }
}
}
Summary/Key Takeaways
- We successfully organized our application using Angular Router and standalone page components.
UsersPageComponentnow hosts theUserListComponentand navigation to add users.AddUserPageComponenthosts theUserFormComponent.- Routes are defined in
app.routes.tsusingcomponentfor standalone components. routerLinkandrouterLinkActivedirectives are used for declarative navigation and active link styling.- The
router-outletinAppComponentdynamically renders the content of the active route.
Our application now has a clean and navigable structure. In the next chapter, we’ll enhance the user experience by implementing better error handling and loading states across our application.