Configuração de Rotas e Implementação de Guardas de Navegação em Angular

Visão Geral da Estrutura do Projeto

Uma aplicação Angular típica com múltiplos componentes para gerenciamento de rotas e autenticação. Os componentes principais incluem:

  • ComponenteRaiz
  • ComponentePrincipal
  • ComponenteCabecalho
  • ComponenteMenuLateral
  • ComponenteProduto
  • ComponenteConteudo
  • ComponenteDialogoPersonalizado
  • ComponenteLivros
  • ComponenteAluno
  • ComponenteProfessor
  • ComponenteBemVindo
  • ComponenteAutenticacao

Layout do Componente Principal

<div class="container-grid">
    <div class="cabecalho">
        <app-cabecalho></app-cabecalho>
    </div>
    <div class="menu-lateral">
        <app-menu></app-menu>
    </div>
    <div class="area-conteudo">
        <app-conteudo></app-conteudo>
    </div>
</div>

Componente Raiz

<router-outlet></router-outlet>

Componente Conteúdo com Rotas Filhas

<router-outlet></router-outlet>

Configuração de Rotas (arquivo rotas-principal.module.ts)

import { NgModule } from '@angular/core';
import { RouterModule, Rotas } from '@angular/router';
import { ComponentePrincipal } from './componentes/principal/principal.componente';
import { ComponenteCabecalho } from './componentes/cabecalho/cabecalho.componente';
import { ComponenteMenuLateral } from './componentes/menu/menu.componente';
import { ComponenteProduto } from './componentes/produto/produto.componente';
import { ComponenteConteudo } from './componentes/conteudo/conteudo.componente';
import { ComponenteAluno } from './componentes/aluno/aluno.componente';
import { ComponenteProfessor } from './componentes/professor/professor.componente';
import { ComponenteLivros } from './componentes/livros/livros.componente';
import { ComponenteBemVindo } from './componentes/bemvindo/bemvindo.componente';
import { ComponenteAutenticacao } from './componentes/autenticacao/autenticacao.componente';
import { ServicoGuardaAutenticacao } from './servicos/guarda-autenticacao.servico';

const rotas: Rotas = [
  { caminho: '', redirecionarPara: '/principal/conteudo/bemvindo', correspondencia: 'completa' },
  { caminho: 'autenticacao', componente: ComponenteAutenticacao },
  { caminho: 'principal', redirecionarPara: '/principal/conteudo/bemvindo', correspondencia: 'completa' },
  {
    caminho: 'principal', componente: ComponentePrincipal,
    filhos: [
      { caminho: 'cabecalho', componente: ComponenteCabecalho },
      { caminho: 'menu', componente: ComponenteMenuLateral },
      {
        caminho: 'conteudo', componente: ComponenteConteudo,
        filhos: [
          { caminho: '', redirecionarPara: '/principal/conteudo/bemvindo', correspondencia: 'completa' },
          { caminho: 'bemvindo', componente: ComponenteBemVindo },
          { caminho: 'produto', componente: ComponenteProduto, canActivate: [ServicoGuardaAutenticacao] },
          { caminho: 'aluno', componente: ComponenteAluno },
          { caminho: 'livro', componente: ComponenteLivros },
          { caminho: 'professor', componente: ComponenteProfessor }
        ]
      }
    ]
  },
  { caminho: '**', redirecionarPara: 'autenticacao' }
];

@NgModule({
  importacoes: [RouterModule.forRoot(rotas)],
  exportacoes: [RouterModule]
})
export class RotasPrincipalModule { }

Implementação do Serviço Guarda de Navegação

import { Injectable } from '@angular/core';
import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, UrlTree, Router } from '@angular/router';
import { Observable } from 'rxjs';

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

  constructor(private roteador: Router) { }

  canActivate(
    proximo: ActivatedRouteSnapshot,
    estado: RouterStateSnapshot
  ): boolean | Observable<boolean> | UrlTree | Promise<boolean | UrlTree> {
    const autenticado = localStorage.getItem('dados_login');
    if (!autenticado) {
      this.roteador.navigate(['/autenticacao']);
      return false;
    }
    return true;
  }
}

Componente de Autenticacao - Template HTML

<div class="formulario-login">
    <div class="campos">
        <div class="campo">
            <label for="nomeUsuario"></label>
            <span class="icone-entrada">
                <i class="pi pi-user"></i>
                <input type="text" id="nomeUsuario" placeholder="Nome de usuário" [(ngModel)]="nomeUsuario"/>
            </span>
            <small *ngIf="!nomeUsuario" class="erro">Nome de usuário obrigatório</small>
        </div>

        <div class="campo">
            <label for="senha"></label>
            <span class="icone-entrada">
                <i class="pi pi-lock"></i>
                <input type="password" id="senha" [(ngModel)]="senha" placeholder="Senha"/>
            </span>
            <small *ngIf="!senha" class="erro">Senha obrigatória</small>
        </div>

        <div class="botoes">
            <button type="button" (click)="efetuarLogin()">Entrar</button>
        </div>
    </div>
</div>
<p-toast posicao="topo-centro"></p-toast>

Lógica do Componente de Autenticação (TypeScript)

import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { ServicoMensagens } from 'primeng/api';

@Component({
  seletor: 'app-autenticacao',
  templateUrl: './autenticacao.componente.html',
  styleUrls: ['./autenticacao.componente.scss'],
  provedores: [ServicoMensagens]
})
export class ComponenteAutenticacao implements OnInit {
  nomeUsuario: string;
  senha: string;

  constructor(
    private roteador: Router,
    private servicoMensagem: ServicoMensagens
  ) {
    this.nomeUsuario = '';
    this.senha = '';
  }

  ngOnInit(): void { }

  efetuarLogin() {
    if (this.nomeUsuario === 'admin' && this.senha === 'senha123') {
      const informacoesLogin = { usuario: this.nomeUsuario, chave: this.senha };
      localStorage.setItem('dados_login', JSON.stringify(informacoesLogin));
      this.roteador.navigate(['/principal/conteudo']);
    } else {
      this.servicoMensagem.add({ severidade: 'erro', resumo: 'Erro', detalhe: 'Credenciais inválidas' });
    }
  }
}

Validação do Fluxo de Rotas

Ao tentar acessar a rota principal/conteudo/produto sem autanticação, o usuário é redirecionado para a página de login. Após inserir as credenciais corretas, a rota torna-se acessível. Removendo os dados do localStorage e atualizando a página, o redirecionamento ocorre novamente, confirmando o funcionamento do guarda de navegação.

Tags: Angular angular-router canactivate primeng autenticacao

Publicado em 6-23 06:23