• 20 heures
  • Moyenne

Ce cours est visible gratuitement en ligne.

course.header.alt.is_video

course.header.alt.is_certifying

J'ai tout compris !

Mis à jour le 28/11/2019

Profitez des native features : la géolocalisation

Connectez-vous ou inscrivez-vous gratuitement pour bénéficier de toutes les fonctionnalités de ce cours !

La géolocalisation

Pour intégrer les lieux à votre application, vous allez utiliser un package tiers.  Depuis la ligne de commande pour votre projet, installez @agm/core  :

npm install --save @agm/core

Ensuite, vous aurez besoin d'une clé API pour Google Maps.  Vous pouvez créer la vôtre ici :

https://developers.google.com/maps/documentation/javascript/get-api-key?hl=en#key

Une fois votre clé API créée, il faut intégrer AGM dans votre  AppModule  :

imports: [
    BrowserModule,
    IonicModule.forRoot(MyApp),
    AgmCoreModule.forRoot({apiKey: 'AIzaSyDtomsm7eXWYIgxXUVzzuURGRJYWxwTbb8'})
  ],

La page  SetCoordinatesPage  sera affichée dans une modal en utilisant  ModalController  (à importer et à injecter dans  NewViewPage  ) :

import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { ModalController } from 'ionic-angular';
import { SetCoordinatesPage } from '../set-coordinates/set-coordinates';

@Component({
  selector: 'page-new-view',
  templateUrl: 'new-view.html',
})
export class NewViewPage implements OnInit {

  natureViewForm: FormGroup;
  latitude: number;
  longitude: number;
  imageUrl: string;

  constructor(private formBuilder: FormBuilder,
              private modalCtrl: ModalController) {
  }

  ngOnInit() {
    this.initForm();
  }

  initForm() {
    this.natureViewForm = this.formBuilder.group({
      name: ['', Validators.required],
      date: [new Date().toISOString(), Validators.required],
      description: ['']
    });
  }

  onOpenCoordsModal() {
    let modal = this.modalCtrl.create(SetCoordinatesPage);
    modal.present();
  }

}

Ainsi vous pouvez ajouter un bouton pour y accéder dans le template :

    <button ion-button full icon-left (click)="onOpenCoordsModal()">
      <ion-icon name="flag"></ion-icon>
      Ajouter lieu
    </button>

Vous pouvez maintenant commencer à créer  SetCoordinatesPage  :

import { Component, OnInit } from '@angular/core';
import { ViewController } from 'ionic-angular';

@Component({
  selector: 'page-set-coordinates',
  templateUrl: 'set-coordinates.html',
})
export class SetCoordinatesPage implements OnInit {

  latitude: number;
  longitude: number;
  marker: {
    latitude: number,
    longitude: number,
    draggable: true
  };

  constructor(private viewCtrl: ViewController) {}

  ngOnInit() {
    this.latitude = 57.28;
    this.longitude = -2.58;
  }

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

}

Les propriétés latitude et longitude serviront pour centrer la carte (j'ai choisi un endroit près de là où j'ai grandi !) ; l'objet marker vous permettra de présenter un marqueur sur celle-ci, à l'endroit touché par l'utilisateur.

Créez ensuite le template :

<ion-header>
  <ion-navbar>
    <ion-buttons>
      <button ion-button clear (click)="onCancel()">Annuler</button>
    </ion-buttons>
    <ion-title>Ajouter lieu</ion-title>
  </ion-navbar>
</ion-header>

<ion-content padding>
  <agm-map [latitude]="latitude"
           [longitude]="longitude"
           (mapClick)="onMapClicked($event)">
    <agm-marker *ngIf="marker"
                [latitude]="marker.latitude"
                [longitude]="marker.longitude"
                [markerDraggable]="marker.draggable"></agm-marker>
  </agm-map>
</ion-content>

Pour que cette carte s'affiche, il faut ajouter une propriété  height  à son style dans  set-coordinates.scss  :

page-set-coordinates {
  agm-map {
    height: 280px;
  }
}

Maintenant, dans la modal pour  SetCoordinatesPage , la carte s'affiche.  Il faut capturer l'événement venant du  (mapClick)  dans la méthode  onMapClicked() :

  onMapClicked($event) {
    this.marker = {
      latitude: $event.coords.lat,
      longitude: $event.coords.lng,
      draggable: true
    };
  }

Quand l'utilisateur touche la carte, un marqueur apparaît et vous avez les informations correspondant à ses coordonnées.  Mais comment faire pour les passer à  NewViewPage  en fermant la modal ?  Il se trouve qu'il est possible de passer des données en argument de la méthode  dismiss()  : 

  onSave() {
    this.viewCtrl.dismiss({
      latitude: this.marker.latitude,
      longitude: this.marker.longitude
    });
  }

Créez un bouton dans le template qui n'est actif que si le marker existe :

<ion-content padding>
  <agm-map [latitude]="latitude"
           [longitude]="longitude"
           (mapClick)="onMapClicked($event)">
    <agm-marker *ngIf="marker"
                [latitude]="marker.latitude"
                [longitude]="marker.longitude"
                [markerDraggable]="marker.draggable"></agm-marker>
  </agm-map>
  <button ion-button full [disabled]="!marker" (click)="onSave()">Enregistrer</button>
</ion-content>

Mais comment fait-on pour capturer les données venant de la modal qui se ferme ?

Il faut retourner dans  NewViewPage  et dans la méthode  onOpenCoordsModal()  où la modal est créée, et utiliser la méthode  onDidDismiss()  qui capture la fermeture de la modal et les données qui en sortent :

  onOpenCoordsModal() {
    let modal = this.modalCtrl.create(SetCoordinatesPage);
    modal.present();
    modal.onDidDismiss(
      (data) => {
        if (data) {
          this.latitude = data.latitude;
          this.longitude = data.longitude;
        }
      }
    );
  }

Pour montrer qu'un lieu a bien été enregistré, vous pouvez ajouter un item au template :

    <button ion-button full icon-left (click)="onOpenCoordsModal()">
      <ion-icon name="flag"></ion-icon>
      Ajouter lieu
    </button>
    <ion-list *ngIf="latitude">
      <ion-item>
        <p>Latitude : {{ latitude.toFixed(2) }} - Longitude : {{ longitude.toFixed(2) }}</p>
      </ion-item>
    </ion-list>
    <button ion-button
            full
            (click)="onSubmitForm()"
            [disabled]="natureViewForm.invalid">Enregistrer</button>

Les données sont bien enregistrées, mais si l'utilisateur retourne sur  SetCoordinatesPage , le marqueur n'apparaît pas et il doit recommencer à zéro.  De ce fait, il serait plus intéressant de passer les informations du marqueur à  SetCoordinatesPage  et de les traiter si elles existent. Commencez par modifier  onOpenCoordsModal() :

  onOpenCoordsModal() {
    let modal: Modal;
    if (this.latitude) {
      modal = this.modalCtrl.create(
        SetCoordinatesPage,
        {latitude: this.latitude, longitude: this.longitude}
      );
    } else {
      modal = this.modalCtrl.create(
        SetCoordinatesPage
      );
    }
    modal.present();
    modal.onDidDismiss(
      (data) => {
        if (data) {
          this.latitude = data.latitude;
          this.longitude = data.longitude;
        }
      }
    );
  }

Ainsi, si la propriété  latitude est initialisée (ce qui veut dire qu'un marqueur a déjà été créé), la modal ouverte par cette méthode recevra la latitude et la longitude du marqueur déjà créé.  Pour les recevoir dans  SetCoordinatesPage , il faudra injecter  NavParams :

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

@Component({
  selector: 'page-set-coordinates',
  templateUrl: 'set-coordinates.html',
})
export class SetCoordinatesPage implements OnInit {

  latitude: number;
  longitude: number;
  marker: {
    latitude: number,
    longitude: number,
    draggable: true
  };

  constructor(private viewCtrl: ViewController,
              private navParams: NavParams) {}

  ngOnInit() {
    let receivedLatitude = this.navParams.get('latitude');
    let receivedLongitude = this.navParams.get('longitude');
    if (receivedLatitude) {
      this.latitude = receivedLatitude;
      this.longitude = receivedLongitude;
      this.marker = {
        latitude: receivedLatitude,
        longitude: receivedLongitude,
        draggable: true
      }
    } else {
      this.latitude = 57.28;
      this.longitude = -2.58;
    }
  }

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

  onSave() {
    this.viewCtrl.dismiss({
      latitude: this.marker.latitude,
      longitude: this.marker.longitude
    });
  }

  onMapClicked($event) {
    this.marker = {
      latitude: $event.coords.lat,
      longitude: $event.coords.lng,
      draggable: true
    };
  }

}

Tout est prêt maintenant pour intégrer la géolocalisation native du device de l'utilisateur.  D'abord, il faut ajouter le plugin Cordova au projet et installer le plugin Ionic Native correspondant :

ionic cordova plugin add cordova-plugin-geolocation
npm install--save @ionic-native/geolocation

Ensuite, il faut ajouter  Geolocation , importé depuis  @ionic-native/geolocation , aux  providers  dans  AppModule  :

  providers: [
    StatusBar,
    SplashScreen,
    NatureViewService,
    Geolocation,
    {provide: ErrorHandler, useClass: IonicErrorHandler}
  ]

Maintenant, vous pouvez injecter  Geolocation  dans  SetCoordinatesPage .  Injectez également  LoadingController  et  ToastController  pour faire patienter l'utilisateur et pour afficher une éventuelle erreur, et créez une méthode pour la géolocalisation :

import { Component, OnInit } from '@angular/core';
import { LoadingController, NavParams, ToastController, ViewController } from 'ionic-angular';

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

@Component({
  selector: 'page-set-coordinates',
  templateUrl: 'set-coordinates.html',
})
export class SetCoordinatesPage implements OnInit {

  latitude: number;
  longitude: number;
  marker: {
    latitude: number,
    longitude: number,
    draggable: true
  };

  constructor(private viewCtrl: ViewController,
              private navParams: NavParams,
              private geolocation: Geolocation,
              private loadingCtrl: LoadingController,
              private toastCtrl: ToastController) {}

  ngOnInit() {
    let receivedLatitude = this.navParams.get('latitude');
    let receivedLongitude = this.navParams.get('longitude');
    if (receivedLatitude) {
      this.latitude = receivedLatitude;
      this.longitude = receivedLongitude;
      this.marker = {
        latitude: receivedLatitude,
        longitude: receivedLongitude,
        draggable: true
      }
    } else {
      this.latitude = 57.28;
      this.longitude = -2.58;
    }
  }

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

  onSave() {
    this.viewCtrl.dismiss({
      latitude: this.marker.latitude,
      longitude: this.marker.longitude
    });
  }

  onMapClicked($event) {
    this.marker = {
      latitude: $event.coords.lat,
      longitude: $event.coords.lng,
      draggable: true
    };
  }

  onLocateMe() {
    let loader = this.loadingCtrl.create({
      content: 'Recherche de votre position…'
    });
    loader.present();
    this.geolocation.getCurrentPosition().then(
      (resp) => {
        loader.dismiss();
        this.latitude = resp.coords.latitude;
        this.longitude = resp.coords.longitude;
        this.marker = {
          latitude: resp.coords.latitude,
          longitude: resp.coords.longitude,
          draggable: true
        }
      }).catch(
      (error) => {
        loader.dismiss();
        this.toastCtrl.create({
          message: error,
          duration: 3000,
          position: 'bottom'
        }).present();
      }
    );
  }

}

Ajoutez le bouton correspondant au template :

<ion-content padding>
  <agm-map [latitude]="latitude"
           [longitude]="longitude"
           (mapClick)="onMapClicked($event)">
    <agm-marker *ngIf="marker"
                [latitude]="marker.latitude"
                [longitude]="marker.longitude"
                [markerDraggable]="marker.draggable"></agm-marker>
  </agm-map>
  <div text-center>
    <button ion-button round large icon-only (click)="onLocateMe()">
      <ion-icon name="locate"></ion-icon>
    </button>
  </div>
  <button ion-button full [disabled]="!marker" (click)="onSave()">Enregistrer</button>
</ion-content>

La méthode  getCurrentPosition()  retourne plusieurs informations, dont un objet  coords  contenant une latitude et une longitude, que vous utilisez pour recentrer la carte et placer le marqueur.  L'utilisateur peut ensuite modifier sa position s'il le souhaite, et l'enregistrer.  Votre application intègre bien la géolocalisation : il est maintenant temps de permettre à l'utilisateur de prendre une photo.

Exemple de certificat de réussite
Exemple de certificat de réussite