Navegación en Ionic 8: rutas y paso de datos (2026)

📘 ¿Quieres una base sólida de Ionic desde cero? Si prefieres aprender Ionic (y Firebase) de forma ordenada y de principio a fin, en lugar de ir saltando entre tutoriales sueltos, te dejo mi libro: Desarrollo de aplicaciones móviles con Ionic y Firebase desde cero.

Para navegar entre páginas en Ionic 8 usas el router de Angular: defines las rutas con provideRouter, saltas de una página a otra con routerLink (o por código con NavController) y lees los parámetros de la URL con ActivatedRoute. El ion-router-outlet se encarga de las transiciones nativas (deslizar hacia delante y hacia atrás) para que tu app se sienta como una app de verdad, no como una web. En esta guía lo montamos paso a paso con el enfoque moderno de componentes standalone.

Actualizado: julio 2026 — revisado con Ionic 8.8 y Angular standalone.

Aquí tienes el índice completo del tutorial de Ionic para seguir el hilo:

Cómo funciona la navegación en Ionic

Ionic no tiene un sistema de rutas propio: usa directamente el Router de Angular. Lo que aporta Ionic es el ion-router-outlet, una versión del router-outlet de Angular que además aplica las animaciones nativas de transición (empujar la página nueva desde la derecha, volver deslizando hacia la izquierda) y mantiene las páginas en una pila, como hace iOS o Android.

Eso significa que casi todo lo que sabes del router de Angular (rutas, parámetros, guards, lazy loading) te sirve tal cual en Ionic. La diferencia está en un detalle que veremos enseguida: routerDirection, que le dice a Ionic qué animación usar.

Preparar el proyecto y las rutas

Creamos un proyecto con la plantilla blank. Desde Ionic 7 el CLI genera proyectos standalone por defecto (sin NgModule):

ionic start navegacion blank --type=angular
cd navegacion

Generamos una segunda página para tener a dónde ir:

ionic generate page pagina2

En un proyecto standalone las rutas se declaran en app.routes.ts y cada página se carga de forma perezosa (solo cuando se visita) con loadComponent, en lugar del antiguo loadChildren con módulos:

// app.routes.ts
import { Routes } from '@angular/router';

export const routes: Routes = [
  { path: '', redirectTo: 'home', pathMatch: 'full' },
  {
    path: 'home',
    loadComponent: () => import('./home/home.page').then(m => m.HomePage),
  },
  {
    path: 'pagina2',
    loadComponent: () => import('./pagina2/pagina2.page').then(m => m.Pagina2Page),
  },
  {
    // La misma página, pero recibiendo un parámetro :id
    path: 'pagina2/:id',
    loadComponent: () => import('./pagina2/pagina2.page').then(m => m.Pagina2Page),
  },
];

Y en main.ts registramos el router y, muy importante en Ionic, la IonicRouteStrategy (que es la que hace que las páginas se reutilicen y las animaciones funcionen bien):

// main.ts
import { bootstrapApplication } from '@angular/platform-browser';
import { RouteReuseStrategy, provideRouter, withComponentInputBinding } from '@angular/router';
import { provideIonicAngular, IonicRouteStrategy } from '@ionic/angular/standalone';

import { AppComponent } from './app/app.component';
import { routes } from './app/app.routes';

bootstrapApplication(AppComponent, {
  providers: [
    { provide: RouteReuseStrategy, useClass: IonicRouteStrategy },
    provideIonicAngular(),
    provideRouter(routes, withComponentInputBinding()),
  ],
});

(El withComponentInputBinding() lo usaremos más abajo para recibir los parámetros de la ruta de forma automática; puedes dejarlo puesto desde ya.)

Navegar con routerLink (la forma declarativa)

La manera más sencilla de ir a otra página es desde la plantilla, con routerLink. Le añadimos routerDirection="forward" para que Ionic use la animación de «avanzar»:

<!-- home.page.html -->
<ion-header>
  <ion-toolbar>
    <ion-title>Home</ion-title>
  </ion-toolbar>
</ion-header>

<ion-content class="ion-padding">
  <ion-button routerLink="/pagina2" routerDirection="forward">
    Ir a la página 2
  </ion-button>
</ion-content>

Como cada página es standalone, en su .ts hay que importar los componentes que usa la plantilla, incluido RouterLink:

// home.page.ts
import { Component } from '@angular/core';
import { RouterLink } from '@angular/router';
import {
  IonHeader, IonToolbar, IonTitle, IonContent, IonButton,
} from '@ionic/angular/standalone';

@Component({
  selector: 'app-home',
  standalone: true,
  templateUrl: './home.page.html',
  imports: [RouterLink, IonHeader, IonToolbar, IonTitle, IonContent, IonButton],
})
export class HomePage {}

Navegar por código con NavController

Cuando la navegación depende de una acción (validar un formulario, una respuesta del servidor…), necesitas navegar desde el TypeScript. Ionic ofrece NavController, que envuelve al router y aplica la animación correcta. En standalone lo importas desde @ionic/angular/standalone y lo inyectas con inject():

// home.page.ts
import { Component, inject } from '@angular/core';
import { NavController, IonButton, IonContent, IonHeader, IonToolbar, IonTitle } from '@ionic/angular/standalone';

@Component({
  selector: 'app-home',
  standalone: true,
  templateUrl: './home.page.html',
  imports: [IonButton, IonContent, IonHeader, IonToolbar, IonTitle],
})
export class HomePage {
  private nav = inject(NavController);

  irAPagina2() {
    this.nav.navigateForward('/pagina2');
  }
}

Los tres métodos que vas a usar el 99% del tiempo:

  • navigateForward('/ruta') — avanza a una página nueva (animación hacia delante).
  • navigateBack('/ruta') — vuelve (animación hacia atrás).
  • navigateRoot('/ruta') — reinicia la pila de navegación (útil tras un login: no quieres que el botón «atrás» vuelva a la pantalla de acceso).

Y en la plantilla, el botón llama al método:

<ion-button (click)="irAPagina2()">Ir a la página 2</ion-button>

Volver a la página anterior

Para el típico botón de «volver» de la barra superior, Ionic tiene un componente dedicado: ion-back-button. Muestra la flecha de retroceso adecuada según la plataforma (iOS/Android) y vuelve automáticamente. El defaultHref es la ruta a la que ir si el usuario entró directo a esa página (por ejemplo, desde un enlace externo) y no hay historial:

<!-- pagina2.page.html -->
<ion-header>
  <ion-toolbar>
    <ion-buttons slot="start">
      <ion-back-button defaultHref="/home"></ion-back-button>
    </ion-buttons>
    <ion-title>Página 2</ion-title>
  </ion-toolbar>
</ion-header>

<ion-content class="ion-padding">
  <p>Soy la página 2.</p>
</ion-content>

Recuerda importar IonButtons e IonBackButton en el componente. Si prefieres controlar la vuelta por código, usa this.nav.navigateBack('/home').

Pasar datos entre páginas

El caso más habitual: abres un detalle pasándole un id. Se manda como parte de la URL (ruta pagina2/:id que ya declaramos). Navegar es tan simple como incluir el valor:

<!-- Declarativo -->
<ion-button routerLink="/pagina2/42" routerDirection="forward">Ver detalle 42</ion-button>
// O por código
this.nav.navigateForward('/pagina2/42');

Y en la página de destino lo lees. La forma fiable y de siempre es inyectar ActivatedRoute y sacar el parámetro del paramMap:

// pagina2.page.ts
import { Component, inject, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';

@Component({ /* ...standalone... */ })
export class Pagina2Page implements OnInit {
  private route = inject(ActivatedRoute);
  id: string | null = null;

  ngOnInit() {
    this.id = this.route.snapshot.paramMap.get('id'); // "42"
  }
}

Alternativa moderna (Angular 16+): si activaste withComponentInputBinding() en provideRouter (lo hicimos en main.ts), el router puede rellenar solo un input con el mismo nombre que el parámetro. Con las signal inputs queda así de limpio:

import { Component, input } from '@angular/core';

@Component({ /* ...standalone... */ })
export class Pagina2Page {
  // Se rellena automáticamente con el :id de la ruta
  id = input<string>();
}

Y en la plantilla lo lees como una señal: <p>Recibí el id: {{ id() }}</p>. Es más elegante, pero si te da problemas con enlaces directos (deep links), tira del ActivatedRoute clásico, que nunca falla.

¿Y si necesitas pasar un objeto entero, no solo un id? No lo metas en la URL: guárdalo en un servicio compartido (un pequeño store con Angular) o vuelve a pedirlo por su id en el destino con una petición HTTP. Meter objetos serializados en la URL es frágil y feo.

Proteger rutas con un guard

Para impedir el acceso a una página según una condición (por ejemplo, que el usuario haya iniciado sesión) se usan los functional guards, el enfoque actual de Angular (una simple función, sin clases):

// auth.guard.ts
import { inject } from '@angular/core';
import { CanActivateFn, Router } from '@angular/router';
import { AuthService } from './auth.service';

export const authGuard: CanActivateFn = () => {
  const auth = inject(AuthService);
  const router = inject(Router);

  if (auth.estaLogueado()) {
    return true;
  }
  // Redirige al login si no está autenticado
  return router.parseUrl('/login');
};

Se aplica en la ruta con canActivate:

{
  path: 'privado',
  canActivate: [authGuard],
  loadComponent: () => import('./privado/privado.page').then(m => m.PrivadoPage),
}

routerDirection y las animaciones

El detalle que diferencia a Ionic de una web normal es routerDirection, que controla la animación de transición:

  • forward — la página entra desde la derecha (avanzas).
  • back — la página sale hacia la derecha (retrocedes).
  • root — sin animación de pila; sustituye la vista actual (ideal para cambiar de sección desde un menú lateral o unas tabs).

Si no lo indicas, Ionic intenta adivinarlo por el historial, pero especificarlo hace que las transiciones se sientan siempre correctas.

Errores típicos (y cómo evitarlos)

  • Olvidar la IonicRouteStrategy. Sin ella, las páginas no se reutilizan bien y las animaciones y el botón «atrás» se comportan raro. Va sí o sí en los providers de main.ts.
  • El parámetro llega null. Casi siempre es que la ruta no tiene el :id (declaraste pagina2 pero no pagina2/:id), o que el nombre del parámetro no coincide con el que lees en paramMap.get('...').
  • Importaste el componente pero no la directiva. Si usas routerLink en la plantilla, tienes que importar RouterLink en el imports del componente standalone; si no, el enlace no hace nada.
  • La animación va al revés. Especifica routerDirection explícitamente en vez de dejar que Ionic lo adivine.

Botón para navegar de una página a otra en una app Ionic

Seguimos con el tutorial

Ya sabes moverte entre páginas. El siguiente paso es organizar esa navegación con los dos patrones clásicos de una app: el menú lateral con ion-menu y la navegación por tabs. Y cuando quieras traer datos reales a tus páginas, pasa por peticiones HTTP a una API REST y por formularios reactivos.

📘 ¿Quieres aprender Ionic de forma ordenada, no a saltos? Todo esto (navegación, menús, tabs, HTTP, Firebase) y mucho más, paso a paso y con imágenes, en mi libro Desarrollo de aplicaciones móviles con Ionic y Firebase desde cero.

📱 ¿Prefieres que te desarrolle yo la app? Mira mi presupuesto para desarrollo de apps y cuéntame tu idea.

Un saludo, y si aún no lo has hecho no olvides suscribirte a mi blog para no perderte los próximos posts  :-),

También puedes seguirme en Twitter en ‎@revi_apps y no olvides que me ayudas mucho si compartes este post en las redes sociales.

3 comentarios en “Navegación en Ionic 8: rutas y paso de datos (2026)”

  1. Hola
    He hecho dos app diferentes y al ponerla en el movil, una me sustituye la otra.
    Problema supongo del appID.
    Lo cambio en el fichero AndroidManifest.xml pero siempre vuelva a ponerse solo el ID anterior.
    Como cambiarlo definitivamente?
    O como cambiarlo en ionic antes de build android?

    1. Hola Ivo,

      Si estás utilizando apache cordova para empaquetar la aplicación tienes que cambiar el id de la aplicacion en config.xml donde pone:
      widget id=»io.ionic.starter» version=»0.0.1″ xmlns=»http://www.w3.org/ns/widgets» … tienes que cambiar io.ionic.starter por el id de tu aplicación.

      Si estás utilizando capacitor tienes que cambiar el appId en capacitor.config.json

      Un saludo

  2. Jesús Javier Ruiz

    Buenas , necesito ayuda , estoy intentando hacer esto » pasar el id del producto y con el id utilizar un servicio para obtener los datos relacionados con el producto seleccionado » lo he hecho de manera local pero no he logrado hacerlo cuando los datos son traidos de una api , me gustaría tener un poco de ayuda , gracias.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.

Scroll al inicio