Archivo de la etiqueta: pasar datos entre páginas

Tutorial de IONIC: Navegación

Hola a todos, en el post anterior vimos  una app simple, un minijuego de adivinar números que nos sirvió para aprender cómo se programa la lógica de una página en Ionic.

La aplicación era extremadamente sencilla y toda la lógica se desarrollaba en la misma página, sin embargo lo normal en cualquier aplicación que sea mínimamente completa es que tenga varias vistas o páginas y haya que navegar entre ellas.

En el siguiente enlace tienes el índice para acceder al resto de entradas de este tutorial:

Vamos a crear un nuevo proyecto de prueba para observar cómo funciona la navegación entre páginas en ionic.

Nos situamos en la carpeta donde queramos crear nuestro proyecto y desde consola escribimos el siguiente comando:

 ionic start navegacion blank

Seleccionamos Angular como framework y esperamos a que se termine de crear el proyecto.

Nos situamos dentro de la carpeta del proyecto que acabamos de crear:

cd navegacion

Ahora vamos a crear una nueva página para poder navegar entre dos páginas, pero antes de seguir vamos a conocer Ionic Generator, una herramienta de nos ofrece Ionic para crear componentes automáticamente.

Ionic Generator

Nosotros podemos crear las páginas a mano creando una carpeta para nuestra página con su vista html y su controlador .ts, y su archivo de estilo .scss, también podemos crear y configurar otros elementos a mano, pero el cli (command line interface o interfaz de línea de comandos) de ionic nos facilita muchísimo el trabajo. Ionic dispone de una herramienta llamada ionic generator.

Ionic generator nos permite generar plantillas con los componentes que queramos.

Con el siguiente comando obtenemos la lista de elementos disponible que podemos generar con ionic generator:

ionic g

La lista de elementos que podemos generar automáticamente con ionic generator son:

  • page: Páginas.
  • component: Los componentes son un conjunto de html, con su css y su comportamiento que podemos reutilizar en cualquier lugar sin tener que reescribir de nuevo todo.
  • service: Los services son proveedores que se encargan del manejo de datos, bien extraídos de la base de datos, desde una api, etc. En versiones anterioes a la 4 de ionic se llamaban providers.
  • module: Nos permite crear un módulo.
  • class: Nos permite crear una clase.
  • directive: Una directiva sirve para modificar atributos de un elemento.
  • guard: Genera un “guardián” que nos permite crear una protección para permitir que los componentes solo se activen si se cumple alguna condición, como por ejemplo si el usuario está logueado.
  • pipe: Los pipes nos permiten crear filtros para aplicar a la información que mostramos en la plantilla, por ejemplo podemos aplicar un filtro que convierta un texto en mayúsculas.
  • interface: Nos permite crear una interfaz.
  • enum: genera una enumeración.

Veremos con más detalle cada elemento según lo vayamos necesitando, para este ejemplo de momento nos interesa  page así que con las flechas del cursor seleccionamos page y pulsamos enter, después nos pregunta el nombre que queremos darle a la página, le llamamos por ejemplo Pagina2 y pulsamos enter.

También podríamos haber creado la página directamente escribiendo:

ionic g page Pagina2 

Está es la manera que utilizaremos a partir de ahora para crear páginas.

Podemos observar que en la carpeta app se ha creado una nueva carpeta llamada pagina2:

Vemos que al crear una página con ionic generator además del archivo pagina2.page.ts también se genera un archivo pagina2.module.ts y otro pagina2-routing.module.ts en cada página generada, este archivo se utiliza para poder realizar lo que se conoce como Lazy Loading, que permite cargar páginas y recursos bajo demanda acelerando así la carga de las páginas.

En versiones anteriores a ionic 4, utilizábamos algo parecido a esto para navegar hacia una página:

this.navCtrl.push(‘miPagina’);

Aunque todavía se puede utilizar este sistema lo recomendable es utilizar el routing de angular basado en diferentes URL para cada página o componente a mostrar.

Si echamos un vistazo al archivo app-routing.module.ts vemos que contiene lo siguiente:

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

const routes: Routes = [
  { path: '', redirectTo: 'home', pathMatch: 'full' },
  { path: 'home', loadChildren: () => import('./home/home.module').then( m => m.HomePageModule)},
  {
    path: 'pagina2',
    loadChildren: () => import('./pagina2/pagina2.module').then( m => m.Pagina2PageModule)
  },
];

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

Cómo podemos observar contiene una constante llamada Routes donde se han generado automáticamente las rutas a nuestras dos páginas home y Pagina2.

El primer path que se define está vacío y redirecciona a home, esto indica que home será la página por defecto cuando no se especifique ninguna.

Vemos también que la ruta que se especifica en loadChildren de las dos páginas no apunta a componente de la página si no a su módulo, de esta manera se definen las rutas para hacer lazy loading.

Vamos a ver a continuación las diferentes opciones que tenemos para navegar entre páginas.

Navegar entre páginas utilizando routerLink en la plantilla html

Podemos utilizar routerLink directamente para indicar la ruta de la página que queremos mostrar.

Vamos a editar home.page.html, eliminamos el contenido que se genera por defecto y vamos a crear una página sencilla con un botón para ir a la página 2.

<ion-header>
 <ion-toolbar>
   <ion-title>
     Ionic Blank
   </ion-title>
 </ion-toolbar>
</ion-header>
 
<ion-content>
  <div class="ion-padding">
    <ion-button routerLink="/pagina2" routerDirection="forward">Ir a la página 2</ion-button>
  </div>
</ion-content>

Ahora vamos a editar pagina2.page.html y lo dejamos de la siguiente manera:

<ion-header>
  <ion-toolbar>
    <ion-title>Pagina2</ion-title>
  </ion-toolbar>
</ion-header>

<ion-content>
  <div class="ion-padding">
    <p>Soy la página 2</p>
    <ion-button routerLink="/home" routerDirection="back">Volver a home</ion-button>
  </div>
</ion-content>

Aunque no es obligatorio podemos utilizar como en el ejemplo el parámetro routerDirection para indicar la dirección de la animación. Los valores posibles son tres: fordward, back y root, puedes hacer pruebas cambiando el valor de routerDirection para que entiendas mejor qué hace cada uno. 

Vemos que simplemente poniendo la ruta de la página dentro de href podemos navegar entre dos páginas, si ejecutamos ionic serve -l veremos algo como esto:

Navegar entre páginas programáticamente

Si bien podemos navegar entre las distintas páginas de nuestra aplicación utilizando href en un botón o en un ítem de nuestra plantilla html, a veces necesitaremos que se muestre una página desde la lógica del controlador. 

Lo primero que vamos a hacer es modificar el botón de la página home.page.html, en lugar de la propiedad href le vamos a asignar un evento (click) que llame a una función del controlador que vamos a llamar goToPagina2:

<ion-content>
  <div class="ion-padding">
    <ion-button (click)="goToPagina2()" routerDirection="forward">Ir a la página 2</ion-button>
  </div>
</ion-content>

Ahora vamos a editar home.page.ts para crear esta función que nos permita navegar hasta la página 2.

Aunque podríamos importar y utilizar el  Router de angular con el método navigateByUrl, este método no nos permite definir la dirección de la navegación, por lo que es mejor utilizar NavController.

Lo primero que debemos hacer es importar NavController:

import { NavController } from '@ionic/angular';

Ahora debemos inyectarlo en el constructor:

constructor(private navCtrl: NavController){

}

Al inyectar un elemento en el constructor nos permite acceder a sus métodos desde cualquier sitio de la página.

Para finalizar vamos a crear la función goToPagina2 a la que hacíamos referencia desde el botón de la plantilla:

goToPagina2(){
  this.navCtrl.navigateForward('/pagina2');
}

Tenemos tres métodos que podemos utilizar para navegar según la dirección al igual que lo hacíamos cuando hemos utilizado href, estos tres métodos son: navigateForward, navigateBack y navigateRoot.

Una vez más te animo a que experimentes con ellos para que entiendas mejor lo que hace cada uno.

El código completo de home.page.ts quedaría de la siguiente manera:

import { Component } from '@angular/core';
import { NavController } from '@ionic/angular';

@Component({
 selector: 'app-home',
 templateUrl: 'home.page.html',
 styleUrls: ['home.page.scss'],
})
export class HomePage {

 constructor(private navCtrl: NavController){

 }
 goToPagina2(){
   this.navCtrl.navigateForward('/Pagina2');
 }

}

Volver a la página anterior

Para volver a la página anterior podemos utilizar el componente ion-back-button en nuestra plantilla, lo podemos utilizar para poner el típico botón de volver en la cabecera.

Para probarlo vamos a editar el archivo pagina2.page.html y vamos a añadir lo siguiente en la cabecera:

<ion-header>
 <ion-toolbar>
   <ion-title>Pagina2</ion-title>
   <ion-buttons slot="start">
     <ion-back-button defaultHref="/home"></ion-back-button>
    </ion-buttons>
 </ion-toolbar>
</ion-header>

<ion-content>
  <div class="ion-padding">
    <p>Soy la página 2</p>
    <ion-button routerLink="/home" routerDirection="back">Volver a home</ion-button>
  </div>
</ion-content>

Podemos observar que hemos puesto una propiedad llamada defaultHref, con esto le estamos indicando que la ruta por defecto sea /home. Al pulsar este botón vamos a navegar hacia atrás a la página anterior en el historial, si por algún motivo no encontrase la página anterior por defecto cargaría home. 

En este caso como solo tenemos dos páginas coincide que la página anterior siempre va a ser home.

Por otro lado hemos creado el elemento ion-back-button dentro del contenedor ion-buttons, esto nos sirve para contener botones. Podemos observar que ion-buttons tiene un atributo llamado slot  al que hemos asignado el valor start. Con esto le indicamos que los botones que contenga se van a mostrar al inicio, es decir a la izquierda.

El atributo slot indica para indicar la posición o el estilo que van a tener los elementos.

Existen diferentes valores que podemos utilizar con slot, como por ejemplo: item-left, end, start, icon-left, range-left, range-right, icon-only, etc, dependiendo del componente puede aceptar o no diferentes tipos de slot por lo deberemos revisar la documentación del componente para ver qué posibilidades nos ofrece.

Como podemos ver si ejecutamos ionic serve ion-back-button nos ha creado un botón de volver atrás en la cabecera:

Pasando datos entre páginas

Muchas veces nos interesa pasar datos al llamar a una página.

Por ejemplo podemos tener un listado de productos y al pulsar en un producto queremos llamar a una página donde se muestre el detalle de ese producto.

Al utilizar el router de Angular debemos pasar los datos que necesitemos en la url.

Aunque podríamos pasar toda la información del producto en la propia url convertido en json no es lo más práctico, lo más usual es pasar el id del producto y con el id utilizar un servicio para obtener los datos relacionados con el producto seleccionado. Aprenderemos más adelante a crear y utilizar servicios, de momento vamos a ver cómo podemos pasar un id a la página a la que llamamos.

Vamos a seguir haciendo pruebas con el proyecto navegación, lo primero que vamos a hacer es editar el archivo app-routing.module.ts que es el archivo donde de definen las rutas de nuestras páginas. 

Al crear una página con ionic generator ya se crea automáticamente la ruta en app-routing.module.ts , sin embargo para poder añadir datos a la url debemos especificar el nombre del dato que vamos a enviar, en este ejemplo queremos mandar un dato llamado id así que debemos añadir /:id a la ruta de la página 2:

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

const routes: Routes = [
  { path: '', redirectTo: 'home', pathMatch: 'full' },
  { path: 'home', loadChildren: () => import('./home/home.module').then( m => m.HomePageModule)},
  {
    path: 'pagina2/:id',
    loadChildren: () => import('./pagina2/pagina2.module').then( m => m.Pagina2PageModule)
  },
];

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

 

Como podemos observar hemos hemos definido la el path de la ruta de la Pagina2 como:  pagina2/:id  añadiendo /:id por detrás, así después podremos hacer referencia a id desde la página 2.

Ahora vamos a pasarle por ejemplo el id 14 cuando llamamos a la página 2 desde la página Home, para ello editamos el archivo home.page.ts y modificamos la función goToPagina2() añadiendo el número 14 a la url:

goToPagina2(){
  this.navCtrl.navigateForward('/pagina2/14');
}

Por último vamos a ver cómo obtenemos el id en Pagina2, editamos el archivo pagina2.page.ts y lo primero que necesitamos hacer es importar ActivatedRoute para poder obtener los parámetros recibidos en la url:

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

Ahora debemos inyectarlo en el constructor:

constructor(private route: ActivatedRoute) { }

Finalmente en la función ngOnInit que se ejecuta al iniciar la página recogemos el id y simplemente lo vamos a mostrar a través de un alert:

ngOnInit() {
   let id = this.route.snapshot.paramMap.get('id');
   alert(id);
 }

Para recoger el id utilizamos this.route.snapshot.paramMap.get(‘id’).

El código completo de pagina2.page.ts por lo tanto quedaría de la siguiente manera:

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

@Component({
  selector: 'app-pagina2',
  templateUrl: './pagina2.page.html',
  styleUrls: ['./pagina2.page.scss'],
})
export class Pagina2Page implements OnInit {

  constructor(private route: ActivatedRoute) { }

  ngOnInit() {
    let id = this.route.snapshot.paramMap.get('id');
    alert(id);
  } 

}

Si corremos la aplicación con ionic serve veremos que al pasar a la página 2 saca un alert con el número 14.

Puedes descargar o clonar este proyecto desde GitHub en el siguiente link:

https://github.com/edurevilla/libro-ionic-navegacion

Para no hacer este post demasiado largo por hoy lo vamos a dejar aquí. En el próximo post veremos cómo utilizar menús laterales, navegación por tabs etc.

 

Eso es todo por hoy,  nos vemos en el próximo post :).