Guardas de Rotas - Angular
Guardas de rotas (guards) permitem restringir a navegação por determinadas rotas. Por exemplo, se o acesso a um recurso específico exigir autenticação ou outras condições, podemos conceder ou negar o acesso ao usuário com base nessas verificações. Ou seja, os guards protegem o acesso aos recursos.
canActivate
canActivate
canActivate()
type CanActivateFn = (route: ActivatedRouteSnapshot, state: RouterStateSnapshot) =>
Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree;
Ela recebe dois parâmetros: os objetos ActivatedRouteSnapshot
RouterStateSnapshot
id
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) : boolean {
// obtendo o id
console.log(route.params["id"]);
// ...restante do código
}
O resultado do método normalmente retorna um valor booleano: true
false
true
false
Como exemplo, vamos definir o seguinte projeto da aplicação:
helloapp/ ├── src/ │ ├── app/ │ │ ├── about.component.ts │ │ ├── about.guard.ts │ │ ├── app.component.ts │ │ ├── app.config.ts │ │ ├── home.component.ts │ ├── main.ts │ ├── index.html ├── angular.json ├── package-lock.json ├── package.json └── tsconfig.json
Vamos analisar os elementos do projeto. Na pasta src/app
home.component.ts
HomeComponent
import { Component } from "@angular/core";
@Component({
selector: "home-app",
template: `<h2>Principal</h2>`
})
export class HomeComponent { }
No arquivo about.component.ts
AboutComponent
import { Component } from "@angular/core";
@Component({
selector: "about-app",
template: `<h2>Sobre o site</h2>`
})
export class AboutComponent { }
Suponha que desejamos restringir o acesso ao componente AboutComponent
src/app
about.guard.ts
import { ActivatedRouteSnapshot, RouterStateSnapshot } from "@angular/router";
export const aboutGuard = (route: ActivatedRouteSnapshot, state: RouterStateSnapshot) => {
console.log(route.routeConfig?.path); // pode obter várias informações sobre as rotas, parâmetros, etc.
return confirm("Você tem certeza de que deseja continuar?");
};
Aqui, definimos a função aboutGuard
canActivate
confirm()
confirm()
false
true
Além disso, o caminho solicitado é exibido através da propriedade route.routeConfig.path
Agora, vamos definir as referências para os componentes no arquivo app.component.ts
import { Component } from "@angular/core";
import { RouterOutlet, RouterLink } from "@angular/router";
@Component({
selector: "my-app",
standalone: true,
imports: [RouterOutlet, RouterLink],
styles: `a {padding: 3px;}`,
template: `<div>
<h1>Roteamento no Angular</h1>
<nav>
<a routerLink="">Principal</a>
<a routerLink="/about">Sobre o site</a>
</nav>
<router-outlet></router-outlet>
</div>`
})
export class AppComponent {}
No arquivo app.config.ts
import { ApplicationConfig } from "@angular/core";
import { provideRouter, Routes } from "@angular/router";
import { HomeComponent } from "./home.component";
import { AboutComponent } from "./about.component";
import { aboutGuard } from "./about.guard";
// definição das rotas
const appRoutes: Routes = [
{ path: "", component: HomeComponent },
{ path: "about", component: AboutComponent, canActivate: [aboutGuard] }
];
export const appConfig: ApplicationConfig = {
providers: [provideRouter(appRoutes)]
};
Para restringir o acesso à rota /about
canActivate: [aboutGuard]
/about

Injeção de Serviços
Freqüentemente, a decisão de permitir o acesso a um recurso depende de dados armazenados. Por exemplo, podemos definir um novo arquivo auth.service.ts
src/app
import { Injectable } from "@angular/core";
@Injectable({
providedIn: "root", // serviço global
})
export class AuthService {
isLoggedIn = true;
login(): void { this.isLoggedIn = true; }
logout(): void { this.isLoggedIn = false; }
}
Aqui, definimos a classe AuthService
isLoggedIn
Agora, vamos modificar o arquivo about.guard.ts
import { inject } from "@angular/core";
import { AuthService } from "./auth.service";
export const aboutGuard = () => {
const authService = inject(AuthService); // obtemos o serviço
return authService.isLoggedIn;
};
Essa é a mesma função aboutGuard
inject()
AuthService
isLoggedIn
canDeactivate
canDeactivate
Comparando com canActivate
canActivate
canDeactivate
canDeactivate
type CanDeactivateFn<T> = (component: T, currentRoute: ActivatedRouteSnapshot, currentState: RouterStateSnapshot,
nextState: RouterStateSnapshot) => Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree;
Vamos supor que queremos controlar a navegação a partir do componente AboutComponent
import { Component } from "@angular/core";
import { RouterLink } from "@angular/router";
@Component({
selector: "about-app",
standalone: true,
imports: [RouterLink],
template: `<h2>Sobre o site</h2>
<button (click)="save()">Salvar</button>`
})
export class AboutComponent {
saved: boolean = false;
save() {
this.saved = true;
}
}
Para simular a funcionalidade, adicionamos a propriedade saved
AboutComponent
save()
saved
true
Para controlar a navegação a partir do AboutComponent
exit.about.guard.ts
src/app
import { AboutComponent } from "./about.component";
export const exitAboutGuard = (component: AboutComponent) => {
if (!component.saved) {
return confirm("Você deseja sair da página?");
}
return true;
};
Na função exitAboutGuard
AboutComponent
saved
this.saved
false
Se a função retornar true
false
Para ativar o exitAboutGuard
AboutComponent
app.config.ts
import { ApplicationConfig } from "@angular/core";
import { provideRouter, Routes } from "@angular/router";
import { HomeComponent } from "./home.component";
import { AboutComponent } from "./about.component";
import { exitAboutGuard } from "./exit.about.guard";
// definição das rotas
const appRoutes: Routes = [
{ path: "", component: HomeComponent },
{ path: "about", component: AboutComponent, canDeactivate: [exitAboutGuard] }
];
export const appConfig: ApplicationConfig = {
providers: [provideRouter(appRoutes)]
};
Aqui, no campo da rota, incluímos o parâmetro:
canDeactivate: [exitAboutGuard]
Agora, ao tentar sair do componente AboutComponent
saved
false
