In questo articolo vedremo come iniziare per creare un'applicazione Angular composta da più pagine, per approfondire questo argomento fare riferimento alla seguente documentazione
angular.io/guide/router-tutorial
L'applicazione di esempio è composta da quattro pagine Home, About, Contact e Page Not Found, e implementa Bootstrap 5 per personalizzare i vari componenti, come la barra del menù, il layout, ect...
Iniziamo quindi col creare tramite CLI i quattro Componenti Angular delle pagine HomeComponent, AboutComponent, ContactComponent, PageNotFoundComponent e il componente NavbarComponent per il menù di navigazione, per creare un nuovo componente si usa la seguente sintassi
ng generate component < nome componente >
quindi nel nostro caso
ng generate component home
ng generate component about
ng generate component contact
ng generate component page-not-found
ng generate component navbar
includiamo css e js di bootstrap 5 nel file index.html
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<!-- Bootstrap CSS -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-+0n0xVW2eSR5OomGNYDnhzAbDsOXxcvSN1TPprVMTNDbiYZCxYbOOl7+AMvyTG2x" crossorigin="anonymous" />
<title>Angular Multipage</title>
</head>
<body>
<div class="container">
<div class="row">
<div class="col">
<my-app>loading</my-app>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.1/dist/js/bootstrap.bundle.min.js" integrity="sha384-gtEjrD/SeCtmISkJkNUaaKMoLD0//ElJ19smozuHV6z3Iehds+3Ulb9Bn9Plx0x4" crossorigin="anonymous"></script>
</body>
</html>
quindi creiamo il menù modificando navbar.component.html, in particolare usiamo la direttiva routerLink per definire i link delle pagine
navbar.component.html
<nav class="navbar fixed-top navbar-expand-lg navbar-dark bg-dark">
<div class="container-fluid">
<a class="navbar-brand" routerLink="/">Angular Multipage</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarText" aria-controls="navbarText" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarText">
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
<li class="nav-item">
<a class="nav-link" routerLink="/">Home</a>
</li>
<li class="nav-item">
<a class="nav-link" routerLink="/about">About</a>
</li>
<li class="nav-item">
<a class="nav-link" routerLink="/contact">Contact</a>
</li>
</ul>
</div>
</div>
</nav>
importiamo RouterModule in app.module.ts e definiamo le rotte
app.module.ts
.....
.....
import { RouterModule } from '@angular/router';
@NgModule({
imports: [
.....
.....
RouterModule.forRoot([
{ path: '', component: HomeComponent },
{ path: 'about', component: AboutComponent },
{ path: 'contact', component: ContactComponent },
{ path: '**', component: PageNotFoundComponent }
])
],
.....
.....
})
export class AppModule {}
infine modifichiamo app.component.html includendo il menù di navigazione e la direttiva router-outlet
app.component.html
<app-navbar></app-navbar>
<router-outlet></router-outlet>
Tuttavia se testiamo l'applicazione fin qui creata, possiamo notare che se siamo su un dispositivo mobile e clicchiamo su un link della barra di navigazione, questa rimane aperta pur cambiando correttamente pagina
in pratica l'attributo aria-expanded del bottone con classe .navbar-toggler rimane sul valore true, questo perchè in Angular quando si passa da una pagina all'altra, la pagina non viene aggiornata nel browser, ecco una possibile soluzione
navbar.component.ts
.............
.............
export class NavbarComponent implements OnInit {
expanded = false;
constructor() {}
ngOnInit() {}
setExpanded() {
if (!this.expanded) {
this.expanded = true;
} else {
this.expanded = false;
}
}
NotExpanded() {
if (this.expanded) {
this.expanded = false;
}
}
}
nel componente navbar settiamo una variabile expanded inizialmente su false e due funzioni setExpanded(), NotExpanded(), la prima setterà la variabile expanded su true se la navbar si è espansa, su false se la navbar si chiude, mentre la seconda funzione setta il valore di expanded su false.
Adesso modifichiamo il template del componente navbar utilizzando queste due funzioni in un evento click
navbar.component.html
<nav class="navbar fixed-top navbar-expand-lg navbar-dark bg-dark">
<div class="container-fluid">
<a class="navbar-brand" routerLink="/">Angular Multipage</a>
<button class="navbar-toggler" (click)="setExpanded()" type="button" data-bs-toggle="collapse"
data-bs-target="#navbarText"
aria-controls="navbarText"
aria-expanded="false"
aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarText">
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
<li class="nav-item">
<a class="nav-link" (click)="NotExpanded()" [attr.aria-expanded]="expanded ? false : null"
[attr.data-bs-target]="expanded ? '#navbarText' : null" [attr.data-bs-toggle]="expanded ? 'collapse' : null"
routerLink="/">Home</a>
</li>
<li class="nav-item">
<a class="nav-link" (click)="NotExpanded()" [attr.aria-expanded]="expanded ? false : null"
[attr.data-bs-target]="expanded ? '#navbarText' : null" [attr.data-bs-toggle]="expanded ? 'collapse' : null"
routerLink="/about">About</a>
</li>
<li class="nav-item">
<a class="nav-link" (click)="NotExpanded()" [attr.aria-expanded]="expanded ? false : null"
[attr.data-bs-target]="expanded ? '#navbarText' : null" [attr.data-bs-toggle]="expanded ? 'collapse' : null"
routerLink="/contact">Contact</a>
</li>
</ul>
</div>
</div>
</nav>
in questo modo assegneremo gli attributi aria-expanded, data-bs-target e data-bs-toggle ai rispettivi link in base al valore della variabile expanded
[attr.aria-expanded]="expanded ? false : null"
[attr.data-bs-target]="expanded ? '#navbarText' : null"
[attr.data-bs-toggle]="expanded ? 'collapse' : null"