2 de març del 2018

Ionic: aplicació per saber l'hora de sortida/posta del sol (IV)

Part IV: Versió amb calendari

Aquest article ens mostrarà com afegir un calendari per escollir el dia en l'aplicació per saber l'hora de sortida i posta de sol.

Fins ara hem vist:

Ara afegirem un calendari senzill per poder escollir el dia. Tenim diferents opcions de calendari per Ionic i Angular. Si no necessitem res molt especial, el millor sol ser anar per una opció que estigui actualitzada, ben documentada i, si pot ser, amb una demostració que permeti veure bé la seva funcionalitat.

Afegim el mòdul de calendari ion2-calendar, que sembla complir tot l'anterior, al projecte. Escollim aquest perquè permet obrir una finestra per escollir la data:
 $ npm install ion2-calendar moment --save

Seguint la documentació, afegim el mòdul a app.module.ts:
 ...
 import { CalendarModule } from "ion2-calendar";
 ...
  imports: [
    BrowserModule,
    HttpClientModule,
    CalendarModule,
    IonicModule.forRoot(MyApp)
  ],
 ...
Ara implementem la funcionalitat desitjada en la pàgina home.ts:
import { Component } from '@angular/core';
import { ModalController } from 'ionic-angular';

import { HttpClient, HttpHeaders, HttpParams } from '@angular/common/http';
import { Geolocation } from '@ionic-native/geolocation';
import { CalendarModal, 
         CalendarModalOptions, 
         CalendarResult 
       } from "ion2-calendar";
import * as moment from 'moment';

@Component({
  selector: 'page-home',
  templateUrl: 'home.html'
})
export class HomePage {
  API: string = "https://api.sunrise-sunset.org/json";
  
  // Estany de Sant Maurici
  lat: number = 42.582104;
  lon: number = 1.0008419;

  sunrise : string;
  sunset : string;

  date : Date = new Date();
  dateMsg: string = "Avui";
  posMsg : string;
  posError : boolean = false;

  constructor(  public http: HttpClient,
                private geolocation: Geolocation,
                public modalCtrl: ModalController
  )
  {
    moment.locale('ca-ES');
  }

  ionViewDidLoad() {
    this.geolocation.getCurrentPosition().then((answer) => {
      this.lat = answer.coords.latitude;
      this.lon = answer.coords.longitude;
      this.posMsg = "Posició actual";
      this.getSunriseSunsetFromApi();

    }).catch((error) => {
       console.log('Error getting location', error);
       this.posMsg = "Per defecte";
       this.posError = true;
       this.getSunriseSunsetFromApi();
     });
  }

  selectDate() {
    const options: CalendarModalOptions = {
      title: 'Escull la data',
      canBackwardsSelected: true,
      closeLabel: "Cancel·lar",
      doneLabel: "Fet",
      weekdays: moment.weekdaysShort(),
      weekStart: 1,
    };
    let myCalendar =  this.modalCtrl.create(CalendarModal, {
      options: options
    });

    myCalendar.present();

    myCalendar.onDidDismiss((date: CalendarResult, type: string) => {
      if(date) {
        console.log(date);
        this.date = date.dateObj;
        this.dateMsg = this.date.toLocaleDateString("ca-ES");
        this.getSunriseSunsetFromApi();
      }
    });
  }

  getSunriseSunsetFromApi() {
    let data = {  lat: this.lat.toString(), 
                  lng: this.lon.toString(),
                  formatted: "0",
                  date: this.date.toISOString().slice(0,10)
                };
    console.log("Calling API with date= "+data.date);

    const params = new HttpParams({fromObject: data});
    const headers = new HttpHeaders().set("Accept", "application/json");
    let options = {headers: headers, params: params, withCredentials: false};

    this.http.get(this.API, options).subscribe(answer => {
      if (answer['status']=="OK") {
        let date_options = {hour: "2-digit", minute: "2-digit"};

        this.sunrise = new Date(answer['results'].sunrise)
                                .toLocaleTimeString("ca-ES", date_options);
        this.sunset = new Date(answer['results'].sunset)
                                .toLocaleTimeString("ca-ES", date_options);
      }
    },
    err => console.log(err)
    );    
  }
}

Observem les modificacions que hi hem fet:
  • [6-10] Importem les classes necessàries pel calendari.
  • [26-27] Declarem noves variables per la data escollida.
  • [33] Afegim el controlador Modal de Ionic per poder obrir el calendari en una finestra.
  • [36] Indiquem el llenguatge a utilitzar per a mostrar dates en el calendari.
  • [54-77] Declarem una nova funció selectDate, que ens permet obrir el calendari per escollir la data i assignar-la a les variables que hem declarat. Aquesta funció es cridarà a partir de la interfície d'usuari, com veurem en el codi de home.html. Els paràmetres de configuració del calendari els hem obtingut de la documentació del mòdul. A l'exemple de codi que es presenta en la documentació simplement hi hem afegit l'assignació a les variables i la crida a l'API.
  • [83] S'ha afegit un nou paràmetre a l'hora de cridar l'API per tal d'utilitzar la data seleccionada enlloc de l'actual.

Les modificacions fetes a home.tml són poques:
 ...
    <ion-item-divider color="light">Data</ion-item-divider>
    <ion-item (click)="selectDate()">
      <ion-icon name="search" item-left color="primary"></ion-icon>
      <ion-note item-right>{{ dateMsg }}</ion-note>
    </ion-item>
 ...
Hi hem afegit una icona i hem canviat el missatge fixe pel contingut de la variable dateMsg, però la part més interessant és la captura de l'event click en el <ion-item>. Utilitzem les opcions per capturar les interaccions de l'usuari que ens proporciona Angular. En aquest cas, el que es fa és cridar la funció selectDate del nostre controlador (la que obre el calendari i crida l'API amb la nova data seleccionada).

Podem provar el codi en el navegador, com sempre amb:
 $ ionic serve -c -s
En fer clic en la fila de la data, s'obre una finestra amb el calendari:

 Podem veure en la consola l'objecte que rep el calendari. Tot seguit, en escollir una nova data i tancar la finestra, es crida l'API i la pantalla s'actualitza amb la nova informació:


Observem com s'ha actualitzat la data i les hores de sortida/posta del sol, i també podem comprovar en la consola com s'ha cridat l'API amb la data que s'havia escollit.

Com sempre, teniu tot el codi a la vostre disposició en el Github: v0.3 (amb calendari).

En la propera modificació, podríem permetre canviar el lloc, enlloc d'utilitzar la posició actual.

Seguiu l'evolució de l'aplicació:

2 comentaris:

  1. hi
    can u just send me the link from where you got the code

    ResponElimina
  2. All the code is available in Github. And if you refer to the calendar module, it is referenced in the post, like all the other modules mentioned in the series.

    ResponElimina