Navegação no Ionic com Angular Router: rotas, parâmetros e guards básicos

Capítulo 7

Tempo estimado de leitura: 8 minutos

+ Exercício

O que é o Angular Router no Ionic

No Ionic com Angular, a navegação entre telas é feita pelo Angular Router. Em vez de “abrir páginas” manualmente, você define um conjunto de rotas (URLs internas do app) e o Router decide qual componente deve ser exibido no ion-router-outlet. Isso traz benefícios como: navegação previsível, suporte a parâmetros na URL, guards (proteção de rotas) e organização por funcionalidades (features).

Conceitos essenciais

  • Rota: mapeia um caminho (ex.: /produtos) para um componente ou módulo.
  • Parâmetro de rota: parte variável do caminho (ex.: /produtos/42 onde 42 é o id).
  • Query params: parâmetros após ? (ex.: /produtos?categoria=livros).
  • Link declarativo: navegação via template com [routerLink].
  • Navegação programática: navegação via TypeScript com Router.
  • Guard: classe que decide se uma rota pode ser acessada (ex.: exigir login).

Passo a passo: criando rotas e navegando por links

Suponha que você tenha duas telas: HomePage e ProductsPage, e uma tela de detalhe ProductDetailPage.

1) Definindo rotas no App Routing

No arquivo app-routing.module.ts, defina rotas principais e use loadChildren para carregar módulos de páginas/feature (lazy loading), mantendo o app leve.

import { NgModule } from '@angular/core';
import { PreloadAllModules, RouterModule, Routes } from '@angular/router';

const routes: Routes = [
  { path: '', redirectTo: 'home', pathMatch: 'full' },

  {
    path: 'home',
    loadChildren: () => import('./pages/home/home.module').then(m => m.HomePageModule)
  },
  {
    path: 'products',
    loadChildren: () => import('./features/products/products.module').then(m => m.ProductsModule)
  },

  // fallback opcional
  { path: '**', redirectTo: 'home' }
];

@NgModule({
  imports: [RouterModule.forRoot(routes, { preloadingStrategy: PreloadAllModules })],
  exports: [RouterModule]
})
export class AppRoutingModule {}

Note que products aponta para um módulo de feature (features/products), o que facilita manutenção e crescimento do app.

2) Rotas dentro de uma feature (organização por funcionalidade)

Crie um módulo de rotas específico para a feature, por exemplo: features/products/products-routing.module.ts. Esse arquivo concentra as rotas relacionadas a produtos.

Continue em nosso aplicativo e ...
  • Ouça o áudio com a tela desligada
  • Ganhe Certificado após a conclusão
  • + de 5000 cursos para você explorar!
ou continue lendo abaixo...
Download App

Baixar o aplicativo

import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { ProductsPage } from './pages/products/products.page';
import { ProductDetailPage } from './pages/product-detail/product-detail.page';

const routes: Routes = [
  { path: '', component: ProductsPage },
  { path: ':id', component: ProductDetailPage }
];

@NgModule({
  imports: [RouterModule.forChild(routes)],
  exports: [RouterModule]
})
export class ProductsRoutingModule {}

Com isso, você obtém:

  • /products → lista
  • /products/123 → detalhe do produto 123

3) Navegação com routerLink (template)

Em uma lista de produtos, você pode criar links para o detalhe usando [routerLink]. Exemplo em products.page.html:

<ion-list>
  <ion-item
    *ngFor="let p of products"
    [routerLink]="['/products', p.id]"
  >
    <ion-label>
      <h2>{{ p.name }}</h2>
      <p>R$ {{ p.price }}</p>
    </ion-label>
  </ion-item>
</ion-list>

Boas práticas:

  • Prefira [routerLink] para links simples (mais declarativo e fácil de manter).
  • Use array de segmentos (['/products', id]) para evitar erros de concatenação.

4) Navegação programática (TypeScript)

Quando você precisa navegar após uma ação (ex.: salvar formulário), use o Router.

import { Component } from '@angular/core';
import { Router } from '@angular/router';

@Component({
  selector: 'app-products',
  templateUrl: './products.page.html'
})
export class ProductsPage {
  constructor(private router: Router) {}

  goToDetail(id: string) {
    this.router.navigate(['/products', id]);
  }
}

Rotas com parâmetros e query params

Parâmetros de rota: lendo o :id no TypeScript

Na rota /products/:id, o :id é um parâmetro. Para ler esse valor no componente de detalhe, use ActivatedRoute.

import { Component, OnDestroy, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { Subscription } from 'rxjs';

@Component({
  selector: 'app-product-detail',
  templateUrl: './product-detail.page.html'
})
export class ProductDetailPage implements OnInit, OnDestroy {
  productId!: string;
  private sub?: Subscription;

  constructor(private route: ActivatedRoute) {}

  ngOnInit() {
    // Recomendado quando a mesma página pode ser reutilizada com outro id
    this.sub = this.route.paramMap.subscribe(params => {
      this.productId = params.get('id') ?? '';
      // aqui você buscaria os dados do produto com esse id
    });
  }

  ngOnDestroy() {
    this.sub?.unsubscribe();
  }
}

Alternativa quando você sabe que o valor não mudará durante a vida do componente (menos flexível):

this.productId = this.route.snapshot.paramMap.get('id') ?? '';

Query params: filtragem e estado na URL

Query params são úteis para filtros, ordenação e paginação. Exemplo: /products?category=books&sort=price.

1) Criando um link com query params

<ion-button
  [routerLink]="['/products']"
  [queryParams]="{ category: 'books', sort: 'price' }"
>
  Ver livros por preço
</ion-button>

2) Lendo query params no TypeScript

import { Component, OnDestroy, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { Subscription } from 'rxjs';

@Component({
  selector: 'app-products',
  templateUrl: './products.page.html'
})
export class ProductsPage implements OnInit, OnDestroy {
  category?: string;
  sort?: string;
  private sub?: Subscription;

  constructor(private route: ActivatedRoute) {}

  ngOnInit() {
    this.sub = this.route.queryParamMap.subscribe(q => {
      this.category = q.get('category') ?? undefined;
      this.sort = q.get('sort') ?? undefined;
      // aplique filtros/ordenação na lista
    });
  }

  ngOnDestroy() {
    this.sub?.unsubscribe();
  }
}

3) Atualizando query params sem perder os existentes

Um padrão comum é alterar apenas um parâmetro e manter os demais. Use queryParamsHandling: 'merge'.

import { Router } from '@angular/router';

constructor(private router: Router) {}

setSort(sort: string) {
  this.router.navigate([], {
    queryParams: { sort },
    queryParamsHandling: 'merge'
  });
}

Guards básicos: protegendo telas (exigir login)

Guards permitem bloquear (ou redirecionar) o acesso a rotas com base em regras. Um caso típico é exigir que o usuário esteja autenticado para acessar páginas como perfil, pedidos, checkout etc.

Estratégia simples e funcional

  • Um AuthService expõe o estado de login.
  • Um AuthGuard verifica esse estado.
  • Rotas protegidas usam canActivate.
  • Se não estiver logado, o guard redireciona para /login e pode guardar a URL de retorno.

1) Criando um AuthService (exemplo mínimo)

Exemplo didático com estado em memória. Em apps reais, você pode integrar com token, storage seguro etc., mas o padrão de consumo via guard é o mesmo.

import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';

@Injectable({ providedIn: 'root' })
export class AuthService {
  private loggedIn$ = new BehaviorSubject<boolean>(false);

  isLoggedIn() {
    return this.loggedIn$.value;
  }

  login() {
    this.loggedIn$.next(true);
  }

  logout() {
    this.loggedIn$.next(false);
  }
}

2) Criando o guard (canActivate)

O guard pode retornar boolean (permite/bloqueia) ou um UrlTree (redireciona). Retornar UrlTree é uma boa prática porque evita navegação “quebrada”.

import { Injectable } from '@angular/core';
import { CanActivate, Router, UrlTree, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
import { AuthService } from '../services/auth.service';

@Injectable({ providedIn: 'root' })
export class AuthGuard implements CanActivate {
  constructor(private auth: AuthService, private router: Router) {}

  canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean | UrlTree {
    if (this.auth.isLoggedIn()) {
      return true;
    }

    // Redireciona para /login e guarda a URL original para voltar depois
    return this.router.createUrlTree(['/login'], {
      queryParams: { returnUrl: state.url }
    });
  }
}

3) Protegendo uma rota com canActivate

Exemplo: proteger a rota /account.

import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { AuthGuard } from './guards/auth.guard';

const routes: Routes = [
  {
    path: 'account',
    canActivate: [AuthGuard],
    loadChildren: () => import('./pages/account/account.module').then(m => m.AccountPageModule)
  },
  {
    path: 'login',
    loadChildren: () => import('./pages/login/login.module').then(m => m.LoginPageModule)
  }
];

@NgModule({
  imports: [RouterModule.forChild(routes)],
  exports: [RouterModule]
})
export class SomeRoutingModule {}

Observação: você pode colocar essas rotas no app-routing.module.ts ou em um módulo de rotas específico, dependendo da organização do projeto.

4) Implementando o retorno após login (returnUrl)

Na página de login, leia o returnUrl (query param) e navegue para ele após autenticar.

import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { AuthService } from '../../services/auth.service';

@Component({
  selector: 'app-login',
  templateUrl: './login.page.html'
})
export class LoginPage implements OnInit {
  returnUrl = '/home';

  constructor(
    private route: ActivatedRoute,
    private router: Router,
    private auth: AuthService
  ) {}

  ngOnInit() {
    this.returnUrl = this.route.snapshot.queryParamMap.get('returnUrl') ?? '/home';
  }

  doLogin() {
    this.auth.login();
    this.router.navigateByUrl(this.returnUrl);
  }
}

Exemplo de botão no template:

<ion-button expand="block" (click)="doLogin()">Entrar</ion-button>

Boas práticas para rotas e guards (manutenção)

Organize por features

  • Crie pastas como features/products, features/account com seus próprios routing.module.ts.
  • Mantenha o app-routing.module.ts com rotas de alto nível e redirecionamentos.

Padronize nomes e caminhos

  • Use nomes consistentes: products, products/:id, account.
  • Evite caminhos duplicados ou muito profundos sem necessidade.

Centralize constantes de rotas (opcional)

Para reduzir strings espalhadas, você pode criar um arquivo com caminhos.

export const AppRoutes = {
  home: '/home',
  products: '/products',
  login: '/login',
  account: '/account'
} as const;

Use UrlTree para redirecionar em guards

  • Prefira return this.router.createUrlTree(...) em vez de chamar navigate() dentro do guard.
  • Isso mantém o fluxo de navegação mais previsível e testável.

Evite lógica de autenticação dentro do guard

  • O guard deve apenas consultar um serviço (ex.: AuthService) e decidir.
  • Regras de login/token/expiração ficam no serviço.

Tabela rápida: quando usar cada tipo de parâmetro

NecessidadeMelhor opçãoExemplo
Identificar recurso (obrigatório)Parâmetro de rota/products/42
Filtro/ordenação (opcional)Query params/products?sort=price
Estado compartilhável por linkQuery params/products?category=books
Estrutura hierárquicaRotas aninhadas/feature routing/account/settings

Agora responda o exercício sobre o conteúdo:

Em um app Ionic com Angular, qual abordagem é mais adequada para proteger uma rota que exige login, redirecionando o usuário para /login e preservando a URL de retorno?

Você acertou! Parabéns, agora siga para a próxima página

Você errou! Tente novamente.

Guards com canActivate centralizam a regra de acesso. Ao retornar um UrlTree para /login com returnUrl, o fluxo de navegação fica previsível e permite voltar à URL original após o login.

Próximo capitúlo

Listas, cards e interação: padrões de UI para conteúdo no Ionic

Arrow Right Icon
Capa do Ebook gratuito Ionic para Iniciantes: aplicativos híbridos com HTML, CSS e TypeScript
33%

Ionic para Iniciantes: aplicativos híbridos com HTML, CSS e TypeScript

Novo curso

21 páginas

Baixe o app para ganhar Certificação grátis e ouvir os cursos em background, mesmo com a tela desligada.