Archivo de la etiqueta: ionic 2 tabs

Tutorial de Ionic – Crear una aplicaci贸n para guardar nuestros sitios geolocalizados – Parte 3: A帽adiendo FAB, marcador y ventana modal.

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

 

隆隆Atenci贸n!! este tutorial se basa en ionic 3 y est谩 desactualizado por lo que es posible que los ejemplos no funcionen en la 煤ltima versi贸n de ionic, haz click aqu铆 para acceder a un tutorial mas actual de Ionic.

Hola a todos:

En el post anterior聽vimos como insertar en nuestra app un mapa de google maps centrado en las coordenadas actuales.
Vamos a continuar desarrollando nuestra app.

Para poder apreciar mejor donde estamos situados vamos a mostrar un marcador personalizado en el mapa que nos indique nuestra posici贸n.

Para el marcador vamos a utilizar una imagen personalizada. La forma correcta de utilizar im谩genes locales en nuestra app es alojarlas en la carpeta src/assets, as铆 que vamos a crear dentro de src/assets una carpeta la la que llamaremos img聽donde alojaremos nuestras im谩genes.

Podemos poner la imagen que queramos como 聽marcador para el mapa. Si no os quer茅is complicar pod茅is dar bot贸n derecho sobre la siguiente imagen y descargarla para utilizarla en este ejemplo:

Bien, una vez descargada la imagen la copiamos en la carpeta img que acabamos de crear.

Ahora para situar el marcador en el mapa editamos el archivo inicio.ts聽y en la funci贸n聽loadMap()聽que muestra el mapa a帽adimos el siguiente c贸digo:

loadMap(){

   let mapContainer = document.getElementById('map');
    this.map = new google.maps.Map(mapContainer, {
      center: this.coords,
      zoom: 12
    });
    
    // Colocamos el marcador
    let miMarker = new google.maps.Marker({
              icon : 'assets/img/ico_estoy_aqui.png',
              map: this.map,
              position: this.coords
          });

}

No hay mucho que comentar, como veis para crear un marcador creamos un objeto google.maps.Marker 聽y le pasamos un objeto como par谩metro donde en icon le indicamos donde se aloja la imagen del icono, en este caso la ruta a la imagen que hemos guardado destro de assets en la carpeta img es ‘assets/img/ico_estoy_aqui.png’, si vuestra imagen se llama de otra forma ten茅is l贸gicamente que poner el nombre de la imagen que vay谩is a utilizar.
En map聽le idicamos la variable que contiene el mapa donde se tiene que situar, es este caso this.map, por ultimo en position聽le asignamos las coordenadas donde se tiene que situar, en este caso le pasamos la variable this.coords que contiene las coordenadas actuales.

Ahora si ejecutamos ionic serve -l veremos en el navegador algo como esto:

Mostrando un marcador en el mapa
Mostrando un marcador en el mapa

Ahora vamos a dar un paso m谩s y vamos a a帽adir un聽FAB (Floating Action Button) es decir bot贸n de acci贸n flotante al mapa.Los FAB son componentes est谩ndar de material design, tienen la forma de un c铆rculo y flotan聽sobre el contenido en una posici贸n fija.

Este FAB lo utilizaremos para a帽adir la posici贸n actual a nuestros sitios, para ello haremos que cuando se pulse en el fav se habra una ventana modal donde mostraremos un peque帽o formulario donde aparecer谩n las coordenadas y la direcci贸n de la posici贸n actual y nos permitir谩 a帽adir una descripci贸n y una fotograf铆a desde la c谩mara de nuestro m贸vil.

Vayamos por partes.

Primero vamos a colocar el FAB en la vista de muestra p谩gina de inicio, editamos el archivo inicio.html y a帽adimos lo聽que esta marcado聽con fondo amarillo.

<!--
聽聽Generated template for the Inicio page.

聽聽See http://ionicframework.com/docs/v2/components/#navigation for more info on
聽聽Ionic pages and navigation.
-->
<ion-header>

  <ion-navbar>
    <ion-title>Inicio</ion-title>
  </ion-navbar>

</ion-header>

<ion-content padding>
  <div id="map"></div>
   <ion-fab right top>
    <button ion-fab (tap)="nuevoSitio()">
      <ion-icon name="pin"></ion-icon>
      <ion-icon name="add"></ion-icon>
    </button>
  </ion-fab>
  </ion-content>

Bien, como vemos tenemos el componente ion-fab al que le indicamos que se sit煤e arriba a la derecha con聽right聽y聽top.

En su interior contiene un bot贸n al que le tenemos que indicar que es del tipo ion-fab.

Con (tap)=”nuevoSitio()”聽le indicamos que cuando se pulse o tape el bot贸n se llame a la funci贸n nuevoSitio()聽que聽definiremos luego en el controlador de la p谩gina.

Despu茅s tenemos dos componentes ion-icon聽para mostrar los iconos en el FAB, uno con el icono pin y otro con el icono add, lo habitual es mostrar un solo icono, pero he querido poner dos para que quede m谩s claro que queremos a帽adir una localizaci贸n.

Si probamos ahora nuestra app tendr谩 un aspecto similar a este:

Bien, ahora vamos a definir la funci贸n聽nuevoSitio()聽en el controlador, editamos el archivo inicio.ts y a帽adimos la siguiente funci贸n debajo de la funci贸n loadMap:

nuevoSitio(){
 // aqu铆 vamos a abrir el modal para a帽adir nuestro sitio.
}

La idea es que al llamar a esta funci贸n desde el FAB se abra un modal para poder a帽adir una descripci贸n y una foto a muestro sitio si lo deseamos, vamos a explicar un poco que son los modales y como se utilizan:

Modales

Los modales son como ventanas que se abren dentro de nuestra aplicaci贸n sin que afecten a la pila de navegaci贸n.

Para crear un modal debemos de crear una p谩gina con el ionic generator.
Desde consola vamos a escribir el siguiente comando para crear el modal donde ir谩 el formulario para introducir el nuevo sitio:

ionic g page modalNuevoSitio

Ahora en inicio.ts debemos importar el componente聽ModalController聽 de la librer铆a ionic-angular, por lo tanto despu茅s de NavController y NavParams importamos tambi茅n ModalController.

import { NavController, NavParams, ModalController } from 'ionic-angular';

Debemos inyectar tambi茅n en el constructor el componente ModalController al que hemos llamado modalCtrl:

constructor(
    public navCtrl: NavController,
    public navParams: NavParams,
    private geolocation: Geolocation,
    public modalCtrl : ModalController,
    platform: Platform) {

    ......

Ahora ya estamos listos para crear el modal en nuestra funci贸n nuevoSitio.

Para crear un modal utilizamos el m茅todo聽create del componente ModalController聽y le pasamos como primer par谩metro un string con el nombre del 聽controlador de la p谩gina que hemos creado para el modal llamado聽ModalNuevoSitioPage.
El segundo par谩metro es opcional y se utiliza para pasarle datos a nuestro modal, en este caso lo vamos a utilizar para pasarle el objeto聽this.coords que contiene las coordenadas que hemos obtenido.

Una vez creado el modal para que se muestre en pantalla invocamos al m茅todo present();

nuevoSitio(){
  // aqu铆 vamos a abrir el modal para a帽adir nuestro sitio.
   let mimodal = this.modalCtrl.create( 'ModalNuevoSitioPage',this.coords );
   mimodal.present();
}

Ahora que sabemos como mostrar un modal y como pasarle datos desde la p谩gina que lo llama, vamos a ver como recibimos esos datos y los mostramos en el modal.

Recordad que al usar lazy loading y declarar la p谩gina del modal en su propio modulo (inicio.module.ts)no debemos declararlo en app.module.ts.

Vamos a crear una variable 聽en el controlador del modal (modal-nuevo-sitio.ts)聽que al igual que en la p谩gina inicio llamaremos coords y sera de tipo any, esta variable al igual que en la p谩gina de inicio va a contener un objeto con la latitud y longitud que recibimos en la llamada.

Para recibir los datos desde la p谩gina que llama al modal solo tenemos que utilizar el m茅todo聽get聽de NavParams聽que ya se importa por defecto al crear una p谩gina. Con navParams controlamos los par谩metros que recibimos.
Dentro de la funci贸n聽ionViewDidLoad聽que se ejecuta al cargar la vista vamos a asignar a cada atributo聽del objeto coords聽 que acabamos de crear el valor que corresponde de la latitud y longitud que recibimos.
Veamos como tiene que quedar el c贸digo de modal-nuevo-sitio.ts en estos momentos:

import { Component } from '@angular/core';
import { IonicPage, NavController, NavParams } from 'ionic-angular';


/*
聽聽Generated class for the ModalNuevoSitio page.

聽聽See http://ionicframework.com/docs/v2/components/#navigation for more info on
聽聽Ionic pages and navigation.
*/
@IonicPage()
@Component({
  selector: 'page-modal-nuevo-sitio',
  templateUrl: 'modal-nuevo-sitio.html'
})
export class ModalNuevoSitioPage {

  coords : any = { lat: 0, lng: 0 }

  constructor(public navCtrl: NavController, public navParams: NavParams) {}

  ionViewDidLoad() {
    console.log('ionViewDidLoad ModalNuevoSitioPage');
    this.coords.lat = this.navParams.get('lat');
    this.coords.lng = this.navParams.get('lng');
  }
}

Ahora que hemos recibido las coordenadas desde la p谩gina inicio vamos a mostrarlas en el modal para comprobar que las recibimos correctamente, para ello vamos a editar el archivo聽modal-nuevo-sitio.html聽y simplemente a帽adimos las coordenadas dentro de ion-content:

<ion-content padding>
  <p>Hemos recibido: {{ coords.lat }}, {{ coords.lng }}<p>
</ion-content>

Si probamos ahora muestra aplicaci贸n observamos que al pulsar el bot贸n (FAB) que hemos creado para a帽adir sitios nos abre una ventana modal donde se muestran las coordenadas que acabamos de recibir, pero tenemos un peque帽o problema, y es que no tenemos forma de cerrar聽el modal, as铆 que antes de editar cualquier otra cosa en la p谩gina vamos a crear un bot贸n de cerrar.

Para cerrar el modal tenemos que importar en el controlador de la pagina del modal (modal-nuevo-sitio.ts) el controlador ViewController e inyectarlo en el constructor.

Luego creamos una funci贸n que vamos a llamar cerrarModal donde utilizaremos 聽el m茅todo聽dismiss de ViewController para cerrarlo:

import { Component } from '@angular/core';
import { IonicPage, NavController, NavParams,  ViewController } from 'ionic-angular';


/*
聽聽Generated class for the ModalNuevoSitio page.

聽聽See http://ionicframework.com/docs/v2/components/#navigation for more info on
聽聽Ionic pages and navigation.
*/
@IonicPage()
@Component({
  selector: 'page-modal-nuevo-sitio',
  templateUrl: 'modal-nuevo-sitio.html'
})
export class ModalNuevoSitioPage {

  coords : any = { lat: 0, lng: 0 }
  constructor(public navCtrl: NavController, public navParams: NavParams, private viewCtrl : ViewController ) {}

  ionViewDidLoad() {
    console.log('ionViewDidLoad ModalNuevoSitioPage');
    this.coords.lat = this.navParams.get('lat');
    this.coords.lng = this.navParams.get('lng');
  }

  cerrarModal(){
    this.viewCtrl.dismiss();
  }

}

Ahora vamos a a帽adir el bot贸n de cerrar que llamar谩 a la funci贸n cerrarModal que acabamos de crear 聽en la cabecera de la vista de la p谩gina del modal (modal-nuevo-sitio.html), aprovechamos tambien para cambiar el t铆tulo del modal a “Nuevo sitio”:

<!--
聽聽Generated template for the ModalNuevoSitio page.

聽聽See http://ionicframework.com/docs/v2/components/#navigation for more info on
聽聽Ionic pages and navigation.
-->
<ion-header>

  <ion-navbar>
    <ion-title>Nuevo sitio</ion-title>
   <ion-buttons start>
      <button ion-button (click)="cerrarModal()">
        <ion-icon name="md-close"></ion-icon>
      </button>
    </ion-buttons>
  </ion-navbar>

</ion-header>

<ion-content padding>
  <p>Hemos recibido: {{ coords.lat }}, {{ coords.lng }}<p>
</ion-content>

Ahora ya tenemos un bot贸n de cerrar para nuestro modal, si hab茅is seguido correctamente todos los pasos al pulsar sobre el FAV聽se聽abrir谩 nuestro modal como en la siguiente imagen:

Por ahora lo dejamos aqu铆, hoy hemos aprendido聽como a帽adir un marcador al mapa de Google maps, como a帽adir a nuestra app botones tipo FAB, y como crear, abrir, pasar datos y cerrar un modal.
En el pr贸ximo post veremos como a帽adir un nuevo 聽con descripci贸n y foto, haciendo uso de la c谩mara del m贸vil.

Si necesitas desarrollar una aplicaci贸n m贸vil no dudes en solicitarme un presupuesto sin compromiso:

Tutorial de Ionic – Crear una aplicaci贸n para guardar nuestros sitios geolocalizados – Parte 2: Mostrando el mapa.

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

Hola a todos:

En el post anterior creamos una aplicaci贸n con tres tabs y vimos como navegar entre ellas.
Hoy vamos a seguir construyendo la aplicaci贸n.Lo siguiente que vamos a hacer es mostrar un mapa en la p谩gina de inicio centrado en las coordenadas actuales donde nos encontremos.

Lo primero que vamos a necesitar es cagar la librer铆a de Google maps , si quieres saber m谩s sobre la api de google maps聽puedes consultar este tutorial.

Editamos el archivo index.html聽que es la plantilla principal que se carga al iniciar la aplicaci贸n聽y a帽adimos la siguiente linea antes de 聽cargar el script 聽build/main.js:

<script src="https://maps.google.com/maps/api/js"></script>

El c贸digo completo quedar铆a as铆:

<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
  <meta charset="UTF-8">
  <title>Ionic App</title>
  <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
  <meta name="format-detection" content="telephone=no">
  <meta name="msapplication-tap-highlight" content="no">

  <link rel="icon" type="image/x-icon" href="assets/icon/favicon.ico">
  <link rel="manifest" href="manifest.json">
  <meta name="theme-color" content="#4e8ef7">

  <!-- cordova.js required for cordova apps -->
  <script src="cordova.js"></script>

  <!-- un-comment this code to enable service worker
聽聽
聽聽聽聽if ('serviceWorker' in navigator) {
聽聽聽聽聽聽navigator.serviceWorker.register('service-worker.js')
聽聽聽聽聽聽聽聽.then(() => console.log('service worker installed'))
聽聽聽聽聽聽聽聽.catch(err => console.log('Error', err));
聽聽聽聽}
聽聽-->

  <link href="build/main.css" rel="stylesheet">

</head>
<body>

  <!-- Ionic's root component and where the app will load -->
  <ion-app></ion-app>

  <!-- The polyfills js is generated during the build process -->
  <script src="build/polyfills.js"></script>

   <script  src="https://maps.google.com/maps/api/js"></script>

  <!-- The bundle js is generated during the build process -->
  <script src="build/main.js"></script>

</body>
</html>

Como vemos esta el la p谩gina principal donde se va a cargar todo el contenido de la app dentro de <ion-app></ion-app> que es componente raid de la aplicaci贸n.

Ahora para poder acceder a las coordenadas del m贸vil entra en juego ionic native.

Con ionic native lo que hacemos es instalar un plugin que nos da acceso a alguna caracter铆stica nativa del m贸vil como la c谩mara, el gps, la br煤jula etc a trav茅s de typescript sin tener que programar nosotros en c贸digo nativo (Java para Android, Swift o objetive c para iOS).

Simplemente instalamos el plugin y luego importamos el plugin de ionic-native.

En la documentaci贸n de ionic 聽podemos ver todos los plugins disponibles en ionic native:

http://ionicframework.com/docs/v2/native/

En esta ocasi贸n necesitamos el plugin聽cordova-plugin-geolocation.
Este plugin proporciona informaci贸n sobre la ubicaci贸n del dispositivo, tales como la latitud y la longitud.

Para instalarlo desde el terminar dentro de la carpeta de nuestro proyecto tenemos que ejecutar los聽siguientes comandos:

ionic cordova plugin add cordova-plugin-geolocation --variable GEOLOCATION_USAGE_DESCRIPTION="La app necesita geolocalizaci贸n"
npm install @ionic-native/geolocation --save

Nos sacar谩 un mensaje diciendo que falta instalar el plugin @ionic/cli-plugin-cordova y nos preguntar谩 si queremos instalarlo, le decimos que si.

Si est谩s utilizando Linux o Mac y te sale un error al intentar instalar el plugin prueba a ejecutar el comando con sudo por delante.

Si os muestra un warning como este:

npm WARN ajv-keywords@2.1.0 requires a peer of ajv@>=5.0.0 but none was installed.

Pode铆s solucionarlo escribiendo el siguiente comando:

npm install ajv@latest

Antes de nada debemos declarar el plugin como provider en el archivo app.module.ts, para ello editamos dicho archivo, importamos el plugin Geolocation y lo a帽adimos en la secci贸n providers:

import { BrowserModule } from '@angular/platform-browser';
import { ErrorHandler, NgModule } from '@angular/core';
import { IonicApp, IonicErrorHandler, IonicModule } from 'ionic-angular';
import { SplashScreen } from '@ionic-native/splash-screen';
import { StatusBar } from '@ionic-native/status-bar';
import { Geolocation } from '@ionic-native/geolocation';


import { MyApp } from './app.component';


@NgModule({
  declarations: [
    MyApp,

  ],
  imports: [
    BrowserModule,
    IonicModule.forRoot(MyApp)
  ],
  bootstrap: [IonicApp],
  entryComponents: [
    MyApp,
  ],
  providers: [
    StatusBar,
    SplashScreen,
    {provide: ErrorHandler, useClass: IonicErrorHandler},
    Geolocation
  ]
})
export class AppModule {}

Bien, ahora vamos a importar el plugin en el controlador de la p谩gina inicio, para ello dentro de la carpeta pages/inicio editamos el archivo inicio.ts聽e importamos el plugin Geolocation de ionic-native.
Tambi茅n vamos a聽importar聽Platform 聽desde ionic-angular para poder acceder al evento ready de Platform聽que se lanza cuando la aplicaci贸n se ha cargado completamente y esta lista. Esto nos evita errores al intentar llamar a un plugin antes de que se haya cargado.

Para importar estos dos m贸dulos incluimos las siguientes lineas en los imports:

import { Geolocation } from '@ionic-native/geolocation';
import { Platform } from 'ionic-angular';

Ahora cuando la aplicaci贸n est茅 completamente cargada y lista (con el evento ready de Platform) vamos a obtener las coordenadas donde nos encontramos y mostrar un mapa centrado en las coordenadas actuales.

Creamos una variable miembro llamada map del tipo any (admite cualquier valor) que contendr谩 el manejador del mapa de google.
Despu茅s para poder utilizar Platform tenemos que inyectarlo como dependencia en el constructor de la clase, tambi茅n debemos inyectar Geolocation en el constructor. En el evento ready de Platform llamaremos a una funci贸n聽que vamos a llamar obtenerPosicion. En estos momentos el c贸digo de inicio.ts deber铆a quedarnos as铆:

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

import { Geolocation } from '@ionic-native/geolocation';
import { Platform } from 'ionic-angular';


/*
聽聽Generated class for the Inicio page.

聽聽See http://ionicframework.com/docs/v2/components/#navigation for more info on
聽聽Ionic pages and navigation.
*/
@IonicPage()
@Component({
  selector: 'page-inicio',
  templateUrl: 'inicio.html'
})
export class InicioPage {

  map: any; // Manejador del mapa.

  constructor(
    public navCtrl: NavController,
    public navParams: NavParams,
   public  platform: Platform,
   private geolocation: Geolocation){

     platform.ready().then(() => {
      // La plataforma esta lista y ya tenemos acceso a los plugins.
        this.obtenerPosicion();
     });

  }

  ionViewDidLoad() {
    console.log('ionViewDidLoad InicioPage');
  }

}

Hagamos un peque帽o par茅ntesis en nuestra app para hablar de un par de conceptos que vamos a utilizar con frecuencia en nuestros desarrollos con ionic 2:

Promesas

Vemos que dentro del constructor lamamos al m茅todo ready()聽 de聽platform聽 y despu茅s de un punto utilizamos la palabra then(…).

Esto es lo que llamamos una promesa.

Normalmente los plugins de聽ionic-native聽nos devuelven una promesa

Las promesas las inclu铆a angular 1 pero ahora las promesas ya son nativas en EMACScript 6.

Las promesas vienen a sustituir a los callbacks. Se ejecuta la 聽funci贸n y cuando obtenemos un resultado en el then se ejecuta el c贸digo que necesitemos.

Si falla la ejecuci贸n de alguno podemos utilizar la funci贸n catch para tratar el error.

Funciones de flecha

Otra cosa que te puede resultar rara es que dentro del then en lugar de ejecutar una funci贸n al uso estamos utilizando lo que se denomina funciones de flecha o en ingl茅s (Fat Arrow functions).

La funciones con flecha permiten crear funciones an贸nimas m谩s f谩cilmente y adem谩s permiten utilizar this en el contexto actual.
Vamos a ver聽un poco m谩s en detalle esto con聽
el siguiente ejemplo:

class MiClase {
  constructor() {
    this.nombre = 'Eduardo';
    setTimeout(() => {
      // Esto imprim茅 en la consola "Eduardo" ya que en las funciones con flecha this hace referencia al contexto actual.
      console.log(this.nombre);
    });
  }
}

Esto ser铆a lo mismo que escribir lo siguiente:

class MiClase {
  constructor() {
    this.nombre = 'Eduardo';
    var _this = this;
    setTimeout(function() {
     console.log(_this.nombre);
    });
  }
}

Ahora que ya conocemos lo que son las promesas y las funciones de flecha podemos seguir con nuestra aplicaci贸n.

Antes de nada vamos a a帽adir una聽variable en en controlador 聽que vamos a vamos a llamar聽coords聽y聽en ella guardaremos un objeto con la latitud y longitud donde nos encontramos.

Por lo tanto encima del constructor de la clase despu茅s de la variable map definimos la variable coords:

...

export class Inicio {

聽聽map: any; // Manejador del mapa.
 coords : any = { lat: 0, lng: 0 }

  constructor(

...

Si el editor os marca los errores observareis que os subraya this.obtenerPosicion(), esto es evidentemente porque estamos llamando a una funci贸n que todav铆a no hemos definido.

Vamos a definir la funci贸n obtenerPosici贸n():

obtenerPosicion():any{
    this.geolocation.getCurrentPosition().then(res => {
      this.coords.lat = res.coords.latitude;
      this.coords.lng = res.coords.longitude;

      this.loadMap();
    })
    .catch(
      (error)=>{
        console.log(error);
      }
    );
  }

La funci贸n聽getCurrentPosition()聽del plugin Geolocation nos devuelve una promesa.

Como podemos observar resolvemos la promesa con una funci贸n de flecha. En la funci贸n de flecha recibimos como par谩metro el objeto res. Lo que nos interesa obtener es la longitud y latitud donde nos encontramos, estos valores est谩n en res.coords.longitude y res.coords.latitude.
Asignamos esos valores al objeto de la variable this.cords que acabamos de definir y despu茅s llamamos a la funci贸n this.loadMap()聽que a煤n no hemos creado.

Recordad que debemos de聽utilizar this聽para hacer referencia a聽las variables聽miembro y m茅todos que definamos en la clase del controlador.

Ahora deberemos crear la funci贸n loadMap聽que se encargar谩 de mostrar un mapa en la p谩gina centrado en las coordenadas que hemos recogido.

Antes de definir la funci贸n necesitamos crear el contenedor donde se va a mostrar el mapa en la vista. La librer铆a javascript de Google maps lo que hace es insertar un mapa en un div, por lo que necesitamos crear ese div en la vista y luego pas谩rselo como referencia para crear el mapa.

Editamos la vista de la p谩gina inicio, es decir el archivo inicio.html聽y a帽adimos un div dentro de ion-content 聽al que le asignamos como id “map”:

<!--
聽聽Generated template for the Inicio page.

聽聽See http://ionicframework.com/docs/v2/components/#navigation for more info on
聽聽Ionic pages and navigation.
-->
<ion-header>

  <ion-navbar>
    <ion-title>Inicio</ion-title>
  </ion-navbar>

</ion-header>


<ion-content padding>

  <div id="map"></div>

</ion-content>

Ahora tenemos que asignarle un tama帽o al mapa as铆 que por primera vez vamos a editar el archivo de estilos de una p谩gina, en este caso vamos a editar el archivo inicio.scss.

La extensi贸n del archivo .scss, hace referencia a que es una archivo Sass, sus siglas hacen referencia a (Syntactically Awesome Stylesheets) algo as铆 como “Hoja de estilo sint谩cticamente impresionante”.

Sass聽es un lenguaje de hoja de estilos que extiende el css tradicional proveyendo de varios mecanismos que est谩n presentes en los lenguaje de programaci贸n. Con Sass puedes utilizar variables,聽c贸digo anidado, mixins, etc.

Ionic ya viene con Sass instalado lo que hace realmente f谩cil su utilizaci贸n. Sass es un lenguaje de script que es traducido a css. Podemos a帽adir reglas聽de estilo de igual manera que lo hacemos con css por lo que de momento para definir el tama帽o del mapa no necesitamos saber mas. Si quieres m谩s informaci贸n sobre Sass puede consultar la documentaci贸n oficial:聽http://sass-lang.com/documentation/

Veamos como tiene que quedar el archivo inicio.scss:

page-inicio {
ion-content{
聽聽聽聽#map {
聽聽聽聽聽聽width: 100%;
聽聽聽聽聽聽height: 100%;
    }
  }
}

Como podemos ver聽dentro del elemento page-inicio definimos el estilo para ion-content聽 y a su vez dentro definimos el estilo para #map al que le estamos diciendo que ocupe todo al ancho y el alto de la p谩gina, como vemos Sass nos permite anidar los elementos.

Bien, una vez hechos estos preparativos ya podemos definir la funci贸n loadMap que se encargar谩 de mostrar un mapa en la pagina centrado en las coordenadas que hemos recogido. Para que聽Typescript no de error por no reconocer la clase google cuando la llamemos desde la funci贸n que vamos a crear, vamos a declarar la variable google justo debajo de los imports con declare聽var聽google:聽any;聽. Veamos como tiene que quedar el c贸digo de聽inicio.ts聽con la variable google definida y nuestra funci贸n loadMap:

import { Component } from '@angular/core';
import { NavController, NavParams } from 'ionic-angular';
import { Geolocation } from '@ionic-native/geolocation';
import { Platform } from 'ionic-angular';

declare var google: any;



/**
聽* Generated class for the Inicio page.
聽*
聽* See http://ionicframework.com/docs/components/#navigation for more info
聽* on Ionic pages and navigation.
*/
@IonicPage()
@Component({
  selector: 'page-inicio',
  templateUrl: 'inicio.html',
})
export class InicioPage {

 map: any; // Manejador del mapa.
 coords : any = { lat: 0, lng: 0 }

  constructor(public navCtrl: NavController, public navParams: NavParams,private geolocation: Geolocation,public  platform: Platform) {
    platform.ready().then(() => {
      // La plataforma esta lista y ya tenemos acceso a los plugins.
        this.obtenerPosicion();
     });

  }

  ionViewDidLoad() {
    console.log('ionViewDidLoad Inicio');
  }

  loadMap(){
   let mapContainer = document.getElementById('map');
    this.map = new google.maps.Map(mapContainer, {
      center: this.coords,
      zoom: 12
    });
}

 obtenerPosicion():any{
    this.geolocation.getCurrentPosition().then(res => {
      this.coords.lat = res.coords.latitude;
      this.coords.lng = res.coords.longitude;

      this.loadMap();
    })
    .catch(
      (error)=>{
        console.log(error);
      }
    );
  }
}

En la funci贸n loadMap()聽asignamos a la variable mapContainer聽el elemento div con id=”map” que hab铆amos creado en la vista y creamos un mapa con google.maps.Map聽donde le pasamos dos par谩metros, el primero es el elemento contenedor del mapa que lo hemos recogido en la variable mapContainer聽y el segundo par谩metro es un objeto donde le pasamos la configuraci贸n del mapa, en este caso le pasamos las coordenadas al par谩metro center聽y le decimos que muestre el mapa con un zoom de 12.

En este punto si probamos nuestra aplicaci贸n en el navegador con ionic serve -l deber铆amos ver algo como esto:

Pantalla de Inicio con nuestro mapa
Pantalla de Inicio con nuestro mapa

Para no hacer demasiado largo este post lo vamos a dejar aqu铆.

En el siguiente post seguiremos desarrollando la app, veremos como a帽adir un bot贸n FAB, como a帽adir un marcador al mapa y como crear una ventana modal y pasarle datos desde el controlador de la p谩gina que hace la llamada.

 
Si necesitas desarrollar una aplicaci贸n m贸vil no dudes en solicitarme un presupuesto sin compromiso:

Tutorial de Ionic – Crear una aplicaci贸n para guardar nuestros sitios geolocalizados – Parte 1 – Navegaci贸n por Tabs

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

 

隆隆Atenci贸n!! este tutorial se basa en ionic 3 y est谩 desactualizado por lo que es posible que los ejemplos no funcionen en la 煤ltima versi贸n de ionic, haz click aqu铆 para acceder a un tutorial mas actual de Ionic.

Hola a todos.

En el cap铆tulo anterior de este tutorial sobre Ionic 2 creamos una app simple, un minijuego de adivinar n煤meros que nos sirvi贸 para prender c贸mo se programa la l贸gica de una p谩gina en Ionic 2.

Vimos c贸mo pasar variables entre el controlador de la p谩gina y la vista y c贸mo llamar a funciones desde un evento de la vista como pulsar un bot贸n.

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.

Hoy vamos a aprender a hacer una aplicaci贸n con varias p谩ginas y veremos c贸mo podemos navegar entre ellas, para ello vamos a realizar una aplicaci贸n de ejemplo.

Descripci贸n de la aplicaci贸n:

La aplicaci贸n consistir谩 en una herramienta que nos permita guardar el lugar donde nos encontramos actualmente recogiendo las coordenadas gracias al gps del m贸vil.

Est谩 aplicaci贸n puede sernos 煤til por ejemplo para recordar donde hemos aparcado el coche o para guardar un restaurante que nos ha gustado y queremos volver m谩s tarde etc.

La aplicaci贸n constar谩 de una pantalla inicial con un mapa donde se mostrar谩 la posici贸n actual y un bot贸n para a帽adir la posici贸n actual. Al pulsar el bot贸n se abrir谩 una ventana modal con un peque帽o formulario donde a帽adir una descripci贸n y un fotograf铆a.

Los lugares que guardemos se mostrar谩n en otra p谩gina que contendr谩 un listado de tus sitios guardados.

Al pinchar sobre uno de nuestros sitios guardados se abrir谩 otra ventana modal donde mostraremos la foto, la direcci贸n y la descripci贸n del mismo.

Bien, vamos a comenzar creando nuestra aplicaci贸n. Desde la consola de comandos o terminal escribimos:

ionic start misSitios blank

Una vez creada nuestro proyecto vemos que por defecto nos ha generado la p谩gina home dentro de la carpeta pages.

Nosotros a priori vamos a utilizar tres p谩ginas, una con el mapa donde se muestra nuestra posici贸n actual, otra con el listado de nuestros sitios guardados y otra que llamaremos info donde mostraremos informaci贸n sobre la aplicaci贸n y que simplemente utilizaremos de relleno para tener una tercera p谩gina y poder mostrar mejor como funciona la navegaci贸n entre p谩ginas.

Las paginas normalmente suelen estar asociadas a “tabs” o pesta帽as y se navega entre ellas cambiando de tab.

Ionic Generator

Nosotros podemos crear las p谩ginas a mano creando una carpeta dentro de la carpeta pages con su vista html y su controlador .ts, y su css, tambi茅n podemos crear y configurar los tabs a mano, pero el cli (command line interface o interfaz de linea 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 --list

Recordad que debemos estar dentro de la carpeta del proyecto para poder ejecutar cualquier comando de ionic, por lo que deberemos escribir cd misSitios desde consola para entrar dentro de la carpeta de nuestro proyecto.

La lista de elements que podemos generar autom谩ticamente con ionic generator son:

  • 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.
  • Directive:
    Una directiva sirve para modificar atributos de un elemento.
  • Page: P谩ginas.
  • Pipe: Los pipes son lo que angular 1 se consideraban filtros.
  • Provider:Los providers son proveedores que se encargan del manejo de datos, bien extra铆dos de la base de datos, desde una api, etc.
  • Tabs: Nos genera la p谩gina maestra de Tabs y una p谩gina para cada tab.

Veremos con m谩s detalle cada elemento seg煤n lo vayamos necesitando, para este ejemplo de momento nos interesan los Tabs.

Seleccionamos Tabs y como 聽nombre le ponemos misTabs, tambi茅n podemos generar directamente los tabs con el siguiente comando:

ionic g tabs misTabs

Al ejecutar el comando primero nos pregunta el n煤mero de tabs que queremos crear, para este ejemplo vamos a utilizar 3.Utilizamos la flecha hacia abajo del cursor para seleccionar el tres y pulsamos enter.

Acto seguido debemos introducir el nombre del primer tab: le damos el nombre de Inicio y pulsamos enter.

Despu茅s nos pide que introduzcamos el nombre para el segundo Tab: A este tab le vamos a llamar Listado.

Pulsamos enter una vez mas y por ultimo introducimos el nombre del tercer tab. Le llamamos Info y pulsamos enter.

captura ionic generator tabs

Hay que tener cuidado al utilizar el comando ionic g tabs porque si alguna de las p谩ginas que creamos con ionic g tabs ya existe la “machaca” y la crea de nuevo vac铆a.

Si echamos un vistazo a las carpetas de nuestro proyecto vemos que en la carpeta /src/pages se han creado cuatro p谩ginas nuevas, una por cada uno de los tabs que acabamos de crear y una cuarta llamada mis-tabs que sera la p谩gina maestra de los tabs.

 

captura-de-pantalla-2017-01-28-a-las-15-57-22

Desde la versi贸n 3 de ionic al crear una p谩gina con ionic generator adem谩s del archivo nombre_pagina.ts tambi茅n se genera un archivo nombre_pagina.module.ts en cada p谩gina generada, este archivo se utiliza para poder realizar lo que se conoce como Lazy Loading, que permite cargar paginas y recursos bajo demanda acelerando as铆 la carga de las p谩ginas.

Esta nueva caracter铆stica es opcional, si no queremos utilizarla, para que no de error deberiamos eliminar el聽archivo xxx.module.ts de todas las p谩ginas.

Para poder realizar lazy loading necesitamos importar IonicPage聽junto con NavController de ionic-angular e incluir el decorador聽@IonicPage() en cada p谩gina. El decorador聽@IonicPage() nos permite definir los deep links directamente en el componente, esto lo hace autom谩ticamente ionic generator al crear una p谩gina.

Como a partir de ahora vamos a utilizar lazy loading, si ionic generator no lo genera autom谩ticamente, tendremos que crear estos elementos a mano.

Si abrimos el archivo mis-tabs.module.ts聽vemos que tiene el siguiente 聽c贸digo:

import { NgModule } from '@angular/core';
import { IonicPageModule } from 'ionic-angular';
import { MisTabsPage } from './mis-tabs';

@NgModule({
  declarations: [
    MisTabsPage,
  ],
  imports: [
    IonicPageModule.forChild(MisTabsPage),
  ],
  exports: [
    MisTabsPage
  ]
})
export class MisTabsPageModule {}

Como vemos 聽importa聽NgModule, IonicPageModule y la propia p谩gina, en este caso MisTabsPage, despu茅s en @NgModule se declara MisTabsPage聽en declarations, en 聽imports con IonicPageModule.forchild(MisTabsPage) y en exports.

Si abrimos el archivo mis-tabs.ts dentro de carpeta mis tabs vemos el siguiente c贸digo:

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

/**
聽* Generated class for the MisTabsPage tabs.
聽*
聽* See https://angular.io/docs/ts/latest/guide/dependency-injection.html for
聽* more info on providers and Angular DI.
*/
@Component({
  selector: 'page-mis-tabs',
  templateUrl: 'mis-tabs.html'
})
@IonicPage()
export class MisTabsPage {

  inicioRoot = 'InicioPage'
  listadoRoot = 'ListadoPage'
  infoRoot = 'InfoPage'


  constructor(public navCtrl: NavController) {}

}

Esta es la pagina maestra donde vamos a controlar la navegaci贸n por tabs.

Vemos que ha creado una variable para cada tab (inicioRoot,listadoRoot,聽e聽infoRoot) y les ha asignado el controlador de una p谩gina a cada uno entre comillas (‘). Al realizar Lazy loading no necesitamos importar las p谩ginas ni declararlas en app.module.ts,聽simplemente se declaran en su propio archivo de modulo y se hace referencia con el nombre de la clase como string, por eso hay que ponerlo entre comillas.

Bien, si ejecutamos ionic seve -l para ver e resultado ahora nos muestra la p谩gina home que se crea por defecto al crear un proyecto ionic vac铆o, tenemos que indicarle a la aplicaci贸n que la p谩gina inicial debe ser la p谩gina maestra con los tabs que acabamos de crear.

Cambiar el root de nuestra aplicaci贸n (P谩gina principal)

Para indicarle a la aplicaci贸n que la p谩gina principal sea la p谩gina maestra de los tabs que acabamos de crear debemos editar el archivo src/app/app.component.ts e importar la pagina MisTabsPage con import y luego a la variable rootPage asignarle el nombre de la clase de la p谩gina que queremos asignar como p谩gina principal, en este caso MisTabsPage.

Dado que nuestro componente聽MisTabsPage est谩 ahora cargado utilizando lazy loaded, no queremos importarlo directamente y hacer referencia a 茅l en cualquier lugar. En su lugar, podemos pasar una cadena que coincida con el componente por lo tanto聽debemos asignar a rootPage la cadena聽‘MisTabsPage’ entre comillas, es decir debemos sustituir:

rootPage = HomePage;

Por:

rootPage = 'MisTabsPage';

El c贸digo del archivo src/app/app.component.ts completo quedar铆a as铆:

import { Component } from '@angular/core';
import { Platform } from 'ionic-angular';
import { StatusBar, Splashscreen } from 'ionic-native';

@Component({
  templateUrl: 'app.html'
})
export class MyApp {
  rootPage = 'MisTabsPage';

  constructor(platform: Platform) {
    platform.ready().then(() => {
      // Okay, so the platform is ready and our plugins are available.
      // Here you can do any higher level native things you might need.
      StatusBar.styleDefault();
      Splashscreen.hide();
    });
  }
}

El import de la p谩gina home ya no lo necesitamos as铆 que podemos eliminarlo. De hecho podemos eliminar la carpeta de la pagina home ya que no la vamos a utilizar en esta aplicaci贸n, eso s铆, antes de borrar la carpeta de la p谩gina home elimina tambi茅n el import y las declaraciones de homePage en el archivo app.module.ts.

El archivo app.component.ts es el punto de entrada de nuestra aplicaci贸n, vemos que se define como un componente que utiliza como plantilla el archivo app.html.

@Component({
  templateUrl: 'app.html'
})

Si vemos el contenido de app.html podemos observar que 煤nicamente contiene la siguiente linea de c贸digo:

<ion-nav [root]="rootPage"></ion-nav>

Le asigna como root (es decir como p谩gina inicial o ra铆z) la variable rootPage, y como a la variable rootPage le hemos asignado la p谩gina MisTabsPage, la aplicaci贸n cargar谩 dentro de <ion-nav> el contenido de la p谩gina MisTabsPage.

De momento no necesitamos modificar nada mas en app.component.ts, solo comentar que por defecto se importa el elemento platform que tiene el m茅todo ready que podemos utilizar para ejecutar acciones que queremos que se produzcan en el momento que la aplicaci贸n est茅 completamente cargada:

platform.ready().then(() => { ... }

De momento lo dejamos como est谩.

Ahora ya podemos ejecutar nuestra aplicaci贸n y ver las tres pesta帽as que nos ha creado:

Nuestra app con tabs
Nuestra app con tabs

Como vemos ha creado por defecto un icono para cada pesta帽a.

Vamos a ver como podemos cambiar los iconos de los tabs para ello vamos ahora a ver el contenido de la plantilla mis-tabs.html:

<ion-tabs>
    <ion-tab [root]="inicioRoot" tabTitle="Inicio" tabIcon="information-circle"></ion-tab>
    <ion-tab [root]="listadoRoot" tabTitle="Listado" tabIcon="information-circle"></ion-tab>
    <ion-tab [root]="infoRoot" tabTitle="Info" tabIcon="information-circle"></ion-tab>
</ion-tabs>

Como podemos observar la p谩gina maestra de los tabs (mis-tabs.html) solamente contiene el contenedor de tabs que se define con la etiqueta <ion-tabs> y luego una etiqueta <ion-tab> por cada tab. Tambi茅n podemos observar que cada tab tiene el atributo [root] donde se le asigna la variable que indica la pagina que se debe mostrar en cada tab.

Luego tenemos el atributo tabTitle al que se le asigna el texto que se muestra en el tab, si solo queremos que se muestre el icono podemos eliminar o dejar vac铆o este atributo.

Y por 煤ltimo tenemos el atributo tabIcon y es aqu铆 donde se le asigna el icono que se muestra en cada tab, si solo queremos que se muestre texto podemos eliminar o dejar vac铆o este atributo.
Si corres la aplicaci贸n en el navegador con ionic serve -l聽puedes observar que en iOS los iconos son diferentes a los iconos de Android. Los iconos cambian dependiendo de la plataforma m贸vil adaptandose al estilo propio de la plataforma. Esta es una de las ventajas de ionic a partir de la versi贸n 2, que no te tienes que preocupar por adaptar el estilo que tu app para cada plataforma ya que la mayor铆a los elementos se adaptan autom谩ticamente al estilo propio de cada sistema.

Probablemente te estar谩s preguntando, pero…驴de donde salen estos iconos?.La respuesta es simple, ionic viene de serie con una colecci贸n de los iconos mas comunes lista para ser usada solamente con asignar como hemos visto el nombre del icono al atributo tabIcon.

El listado de iconos disponibles lo pod茅is consultar el la documentaci贸n oficial de ionic desde el siguiente enlace:聽https://ionicframework.com/docs/ionicons/

El tab Inicio lo vamos a dejar con el icono home, al tab Listado le vamos a asignar el icono list-box y al tab Info le vamos a asignar el icono information-circle:

<ion-tabs>
  <ion-tab [root]="inicioRoot" tabTitle="Inicio" tabIcon="home"></ion-tab>
  <ion-tab [root]="listadoRoot" tabTitle="Listado" tabIcon="list-box"></ion-tab>
  <ion-tab [root]="infoRoot" tabTitle="Info" tabIcon="information-circle"></ion-tab>
</ion-tabs>

Para observar mejor como cambiamos entre las distintas p谩ginas de momento vamos a poner un comentario en cada una.

Editamos inicio.html y dentro de ion-content a帽adimos lo siguiente:

<!--
  Generated template for the Inicio page.

  See http://ionicframework.com/docs/v2/components/#navigation for more info on
  Ionic pages and navigation.
-->
<ion-header>

  <ion-navbar>
    <ion-title>Inicio</ion-title>
  </ion-navbar>

</ion-header>


<ion-content padding>
  <h1>Esta es l谩 p谩gina de inicio, aqu铆 situaremos un mapa con un bot贸n de a帽adir lugar.</h1>
</ion-content>

Editamos listado.html y a帽adimos los siguiente:

<!--
  Generated template for the Listado page.

  See http://ionicframework.com/docs/v2/components/#navigation for more info on
  Ionic pages and navigation.
-->
<ion-header>

  <ion-navbar>
    <ion-title>Listado</ion-title>
  </ion-navbar>

</ion-header>


<ion-content padding>
  <h1>Aqu铆 estar谩 el listado de sitios guardados.</h1>
</ion-content>

Y por 煤ltimo editamos info.html dej谩ndolo de la siguiente manera:

<!--
  Generated template for the Info page.

  See http://ionicframework.com/docs/v2/components/#navigation for more info on
  Ionic pages and navigation.
-->
<ion-header>

  <ion-navbar>
    <ion-title>Info</ion-title>
  </ion-navbar>

</ion-header>


<ion-content padding>
<h1>Mis sitios:</h1>
<p>Aplicaci贸n de muestra del Tutorial de Ionic 2 鈥 Construye Apps m贸viles multiplataforma con ionic 2 desde cero.</p>
</ion-content>

Ahora al navegar por las pesta帽as podemos ver algo parecido a esto:

Nuestras tres pesta帽as en funcionamiento-.
Nuestras tres pesta帽as en funcionamiento.

Como no quiero hacer posts demasiado largos de momento lo dejamos aqu铆. Hoy hemos aprendido a crear una aplicaci贸n con tabs para navegar entre diferentes paginas usando el comando ionic g tabs.

En el pr贸ximo post seguiremos creando nuestra aplicaci贸n para guardar sitios. Insertaremos un mapa en la p谩gina de inicio y capturaremos las coordenadas actuales.

 

Si necesitas desarrollar una aplicaci贸n m贸vil no dudes en solicitarme un presupuesto sin compromiso: