Después de unos días desconectado por vacaciones y preparando también alguna sorpresilla… vuelvo a la carga para responder a la duda de uno de vosotros: ¿Como funcionan las rutas en Ionic 2?
Navegación «nativa»
Supongo que aprendiendo de la experiencia, el equipo de Ionic ha pasado olímpicamente del router de Angular 2 (que por cierto, no ha parado de cambiar desde que lanzaron su primera versión), y ha creado su propio sistema basándose en la navegación nativa de iOS para que la navegación en Ionic 2 sea lo más natural posible.
Esto quiere decir que la navegación está menos orientada a usar URLs (aunque se puede) como en las webs tradicionales, y más orientada al tipo de navegación que se hace desde un móvil, donde es habitual moverse adelante y atrás, o pasar de repente a una sección completamente distinta.
Stack de vistas
El concepto básico de la navegación con Ionic 2 es la pila de vistas (o stack).
Esto es básicamente que vamos apilando las vistas, una encima de otra, cada vez que pasamos a la siguiente vista (hacemos push de la nueva vista), y las quitamos de la pila cuando volvemos atrás (hacemos pop de la vista que queremos quitar) .
Navegación básica
Pongamos como ejemplo la siguiente aplicación inmobiliaria para buscar pisos:
- La vista principal muestra un listado de ciudades
- Al seleccionar la ciudad, se muestra un listado de distritos
- Al seleccionar distrito, la app te lleva a una vista con el listado de pisos de ese distrito
- Al seleccionar un piso, te lleva a la vista de detalle con información del piso
El nuevo sistema de rutas de Ionic 2 te facilita una navegación muy natural:
- En cada selección, se hace push de la vista siguiente
- Si en algún momento, seleccionas el botón atrás, se hace un pop de la vista actual.
Con la animación siguiente lo entenderás de un plumazo.
Vista root
El otro concepto importante es la vista raíz, es decir, la que funciona como base de la pila. En el ejemplo anterior, la vista raíz es la vista «Cities».
Además de poder hacer push/pop de vistas, podemos cambiar también la vista raíz y reiniciar así la pila de vistas tomando como base la nueva vista que hemos asignado como root.
Puedes reiniciar la pila de vistas cambiando directamente la vista raíz.
Si en el ejemplo anterior tuviéramos un menú lateral con la opción de settings y la seleccionamos, este cambio de vista sería claramente una situación en la que nos interesaría cambiar la raíz en lugar de hacer un push de la vista, ya que es un cambio de contexto (la vista de configuración de una app no tiene nada que ver con que estés viendo un listado de apartamentos).
Tabs
Los tabs de Ionic 2 es un caso particular de navegación, ya que en realidad, cada tab esconde su propia pila de vistas, de modo de cuando cambias de tab, lo que haces es cambiar de pila. Esto también es un comportamiento copiado de las aplicaciones iOS, y tiene todo el sentido del mundo.
Quizá si vienes de web no te parece una forma muy lógica de gestionar la navegación entre vistas, pero se adapta perfectamente al comportamiento de navegación en cualquier aplicación móvil.
Hands on code
Está muy bien esto de la teoría, pero te preguntarás… bueno, vale, ¿cómo se hace esto en realidad?
Ion-nav
El componente básico de navegación en Ionic 2 es el <ion-nav>
.
En la vista en la que quieres empezar a tener navegación (normalmente el componente App), debes incluir este componente en el template y pasarle una referencia a la vista que quieres que cargue como raíz.
Esto lo harás con un property binding a la propiedad root
de este componente.
Por ejemplo, si quieres que el sistema de navegación cargue por defecto la vista StartPage
, tienes que hacer esto:
//app.ts
import {StartPage} from 'start'
@Component({
template: '<ion-nav [root]="rootPage"></ion-nav>'
})
class MyApp {
// First page to push onto the stack
rootPage = StartPage;
}
Como ves, en el componente MyApp
declaro una propiedad rootPage
a la que le asigno el componente StartPage
que quiero cargar por defecto. Entonces, en su template, asigno la variable rootPage
a la propiedad root
del <ion-nav>
.
push/pop (NavController)
Para hacer push/pop de vistas, necesitas inyectar el servicio NavController
de Ionic 2.
Pongamos por ejemplo que estás en la vista StartPage
que se ha cargado antes y quieres pasar a la vista SecondPage
al hacer click en un botón.
Tu vista StartPage
necesitará acceder al servicio NavController
para llamar a su método PUSH, además de importar la vista SecondPage
para pasarla como argumento.
Tu vista tendría un aspecto similar a este:
//start-page/start-page.ts
import {Component} from '@angular/core';
import {NavController} from 'ionic-angular';
import { SecondPage } from 'second-page/second-page';
@Component({
template: `
<ion-content>
<button (click)="goToSecondPage()">
Go to SecondPage
</button>
</ion-content>`
})
export class StartPage {
constructor(public navCtrl: NavController) {}
goToSecondPage() {
this.navCtrl.push(SecondPage);
}
}
¿Que quieres volver atrás desde SecondPage
? Fácil, solo necesitas inyectar el servicio NavController
y llamar al método POP:
//second-page/second-page.ts
import {Component} from '@angular/core';
import {NavController} from 'ionic-angular';
@Component({
template: `
<ion-content>
<button (click)="goBack()">
Go back!
</button>
</ion-content>`
})
export class SecondPage {
constructor(public navCtrl: NavController) {}
goBack() {
this.navCtrl.pop();
}
}
Tabs
Como decía, el uso de tabs es un caso particular, en el que cada tab tiene su propio stack de navegación, a partir del cual se puede navegar como siempre con el servicio NavController
.
La diferencia principal se encuentra en el template de la vista principal donde quieres meter la navegación, ya que en lugar de usar un <ion-view>
usarás los componentes <ion-tabs>
y <ion-tab>
.
Veamos un ejemplo:
//myApp.ts
import { Component } from '@angular/core';
import { Tab1 } from './tab1-page';
import { Tab2 } from './tab2-page';
@Component({
template: `
<ion-tabs>
<ion-tab tabIcon="heart" [root]="tab1"></ion-tab>
<ion-tab tabIcon="star" [root]="tab2"></ion-tab>
</ion-tabs>`
})
class MyApp {
tab1: any;
tab2: any;
constructor() {
this.tab1 = Tab1;
this.tab2 = Tab2;
}
}
En el ejemplo puedes ver como el template incluye 2 tabs, donde cada uno tiene su propia root view.
La gracia del componente <ion-tab>
es que el solito es capaz de detectar el click y llevar a cabo el cambio de pila de navegación.
Luego, una vez te encuentras dentro de Tab1 o Tab2, lo único que tienes que hacer es usar NavController
como siempre para navegar dentro de su stack con push y pop.
Conclusiones
Espero que este artículo te haya aclarado el mecanismo de navegación de Ionic 2.
Como conclusiones, te diré (quizás con un punto de vista sesgado por haber trabajado bastante con iOS en el pasado) que me parece una aproximación muy acertada a las necesidades del usuario mobile.
¿Y a ti, te parece acertado? Yo personalmente creo que te va a facilitar el paso de unas vistas a otras mucho más que el sistema ui-router que usaba su predecesor, Ionic 1.
Tiempo al tiempo.
Muy buen artículo pero tengo una duda, ¿se podría utilizar de alguna forma la navegación nativa de ionic (Stack de vistas) en una app pura de angular 2?
Gracias
Ionic 2 utiliza un router diferente del de Angular 2, así que usando directamente el router de Angular 2 no, no es posible. No obstante, Ionic 2 es puramente Angular 2, así que desde tu app angular 2 podrías llegar a usar el router de Ionic 2, importándolo, y añadiendo las restricciones que requiera (entryComponents en el NgModule, por ejemplo). Ten en cuenta que en los últimos meses la declaración de componentes y el proceso de bootstrap ha cambiado un poco, ya lo sabrás de Angular 2.
Saludos
Hola , esta muy bueno el post pero tengo un problema , yo quiero volver atrás con pop pero necesito que al volver a la vista anterior me recargue todo , ya que tengo una llamadas a la api y están se cargan en una lista, como puedo hacerlo ? use el set root pero me abre una nueva vista sobre la anterior y lo que yo quiero es que de una vista vuelva y me recargue la enterior.
Hola Fabian 🙂
Puedes usar los eventos de navegación de Ionic
ionViewWillEnter() {
// Este código siempre se ejecutara cuando cargues la vista
}
Hola, excelente información. Quería preguntarte sobre un error que encuentro constantemente. Veo muchos tutoriales y todos explican paso a paso las cosas, pero solo en el Home, quisiera hacer este ejemplo pero en una página distinta al home, como se hace para que funcione? El ejemplo es el siguiente:
https://ionicacademy.com/accordion-list-ionic/
Si solo tienes una página, lo único que necesitas es renombrar la página «Home» como más prefieras. Si lo que quieres es tener varias páginas, necesitas aprender navegación.
Puedes aprender como hacerlo en mi curso de Ionic 2 (y Ionic 3): https://www.udemy.com/aprende-ionic-2-desde-cero/?couponCode=DESCUENTAZO
¡Saludos!
Buen post, tengo una consulta, en mi proyecto tengo un sidemenu donde tiene Un boton que abre una nueva page, en la nueva page inserte un boton para volver a mi hompage, pero esta lo toma como pila ( es decir que toma la page que abri desde el sidemenu como pagina principal, y mi home lo toma como segunda pagina).
Hay alguna forma de resetear el stack volviendo al home desde la page que abri desde el sidemenu
Excelente post, muchas gracias por clarificar los conceptos.
Te hago una consulta: tengo una app creada con el template tabs, y necesito navegar desde un tab hacia otra pasandole un objeto cómo parámetro. He visto en la documentación que para esto necesito usar this.navCtrl.push(Page, { object }), pero cuando lo hago de esa manera, no se cambia el tab seleccionado, sino que estoy haciendo push sobre el stack de la pagina actual hacia otra página que es otro tab. Entiendo lo que pasa pero no sé como navegar hacia otro tab enviando parámetros.
Si utilizo this.navCtrl.parent.select(1); navego como pretendo pero sin poder pasar el parámetro que necesito.
Gracias de antemano.