Ionic

Using geo points with Ionic framework

Introduction

Parse allows you to associate real-world latitude and longitude coordinates with an object. Adding a ParseGeoPoint to a ParseUser, you will be able to easily find out which user is closest to another, show the locations of the users of your app and also store the user’s location information, among other possibilities.

You can also associate a ParseGeoPoint to any ParseObject. For example, if your app is associated with a store with physical affiliates, you will be able to create a page to show the location of those stores or to show the user which store is closest to him. Another example of this association usage: if your app is a game in which you created ParseObjects to represent characters, adding ParseGeoPoints to these characters would allow them to be shown along the player’s path.

This tutorial explains how to use some features of ParseGeoPoint through Back4App.

After following this tutorial, you will be able to do this:

Geo Points Example App

At any time, you can access the complete Android Project built with this tutorial at our GitHub repository.

Prerequisites

To complete this quickstart, you need:

Step 1 - Set up Google API Key

Install Angular Google Maps - AGM.

$ npm install @agm/core

Import the SDK adding the generated key to ./src/app/app.module.ts.

app.module.ts

1
2
3
4
5
6
7
8
9
@NgModule({
  imports: [
    AgmCoreModule.forRoot({
      // please get your own API key here:
      // https://developers.google.com/maps/documentation/javascript/get-api-key?hl=en
      apiKey: 'API-KEY'
    })
  ]
})

Step 2 - Retrive user’s location

To retrieve user’s location, we’ll need to install Ionic Geolocation plugin.

$ ionic cordova plugin add cordova-plugin-geolocation --variable GEOLOCATION_USAGE_DESCRIPTION="To locate you"
$ npm install --save @ionic-native/geolocation

Now that we installed and imported Geolocation to providers at ./src/app/app.module.ts, let’s implement the get location method and store the results to a class attribute.

home.ts

1
2
3
4
5
6
7
8
  getMyLocation() {
    this.geolocation.getCurrentPosition().then((resp) => {
      console.log('Current Position', resp.coords);
      this.geoposition = resp;
    }).catch((error) => {
      console.log('Error getting location', error);
    });
  }

Step 3 - Create a page to display the map

Now that we have the user location, let’s create a page to display the map, using the already mentioned [Angular Google Maps].

First, run the helper:

$ ionic generate page Maps

Let’s now make it receive a Marker that holds the current position the map is displaying and an array of Markers that will be the pin points around the map.

maps.ts

1
2
3
    let data = this.navParams.get('data');
    this.current = data.current;
    this.markers = data.markers || [];    

Let’s pull up the maps.html now and make it display the data.

maps.html

1
2
3
4
5
6
7
8
9
10
11
12
13
  <agm-map
    [latitude]="current.lat"
    [longitude]="current.lng"
    [zoom]="10"
    [mapTypeId]="'roadmap'">

    <agm-marker
      *ngFor="let m of markers; let i = index"
      [latitude]="m.lat"
      [longitude]="m.lng"
      [label]="m.label">
    </agm-marker>
  </agm-map>  

Step 4 - Showing current user’s location in map

Now we have a page to display the Map locations.

  1. Let’s head back to home.ts and implement a method to display the user’s location on the map.

maps.ts

1
2
3
4
5
6
7
8
  findMyLocation() {
    let current:Marker = {
      lat: this.geoposition.coords.latitude,
      lng: this.geoposition.coords.longitude
    };

    this.navCtrl.push('MapsPage', {data: {current, markers: [current]}});
  }
  1. Let’s make use of Parse easiness now and look for the peers closest to the user location.

home.ts

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
  getClosestUser() {
    let geoPoint = new Parse.GeoPoint(this.geoposition.coords.latitude, this.geoposition.coords.longitude);
    let query = new Parse.Query(Parse.User);
    query.near('Location', geoPoint);
    query.limit(1);

    query.find().then(users => {
      let user = users[0];
      console.log('Closest user', user);

      let current:Marker = {
        lat: user.get('Location').latitude,
        lng: user.get('Location').longitude,
        label: user.get('name')
      };

      let me:Marker = {
        lat: this.geoposition.coords.latitude,
        lng: this.geoposition.coords.longitude,
        label: 'Me'
      };

      this.navCtrl.push('MapsPage', {data: {current, markers: [me, current]}});
    }, err => {
      console.log('Error getting closest user', err)
    })
  }

You can see how simple it is. Basically all we had to do is instantiate a query object for the User collection and make it look for the closest geo location by calling near().

1
2
    let query = new Parse.Query(Parse.User);
    query.near('Location', geoPoint);

Step 5 - Set up Back4App to associate ParseGeoPoint to ParseObjects

Suppose that the example app you are building is associated with a group of stores with physical affiliates. It would be interesting to show all the physical affiliates of this store in the map. In order to do so create a Stores class on Back4pp Dashboard, save the existing stores as ParseObjects, their locations and after that the app will be able to query the physical affiliates and display their possitions on the map. The following steps will help you with that.

  1. Go to Back4App website, login, find your app and open its Dashboard.
  2. Go to Core > Browser > Create a class, as shown in the image below.

    Create a class on B4A

  3. In the field What type of class do you need?, choose the Custom option.

    Class Option

  4. In the field What should we call it?, type “Stores” and then click on Create class button.

    Create class button

  5. Then a new class called “Stores” will be shown and you should insert 2 columns on it: a collumn with data type String called Name, as well as another column with data type GeoPoint called Location. Your class should end up like this:

    Stores Class

  6. Now, fill this class with information. To do so, click on Add a row button in the menu on the top right or in the middle of the page, as shown in the image below.

    Stores Class

  7. Then fill the row with the informations required: the name of the store and its latitude and longitude. After inserting some data, your Stores class should look like the image below. If you want to insert more data, you can click on the Add a row button on the top, or in the + button bellow the last row of data.

    Stores Class with data

Now you are ready to use the location information of the stores in your app.

Step 6 - Display all the stores location on Map

Now that we have the stores location stored, let’s code a method to get the objects and display them.

home.ts

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
  getAllStores() {
    let query = new Parse.Query('Store');

    query.find().then(stores => {
      console.log('Stores', stores);

      let markers = stores.map(s => {
        return {
          lat: s.get('Location').latitude,
          lng: s.get('Location').longitude,
          label: s.get('name')
        };
      });

      this.navCtrl.push('MapsPage', {data: {current: markers[0], markers}});
    }, err => {
      console.log('Error getting closest user', err)
    })
  }

Easy, right? Now, let’s get the CLOSEST one.

home.ts

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
  getClosestStore() {
    let geoPoint = new Parse.GeoPoint(this.geoposition.coords.latitude, this.geoposition.coords.longitude);
    let query = new Parse.Query('Store');
    query.near('Location', geoPoint);
    query.limit(1);

    query.find().then(stores => {
      let store = stores[0];
      console.log('Closest user', store);

      let current:Marker = {
        lat: store.get('Location').latitude,
        lng: store.get('Location').longitude,
        label: store.get('name')
      };

      let me:Marker = {
        lat: this.geoposition.coords.latitude,
        lng: this.geoposition.coords.longitude,
        label: 'Me'
      };

      this.navCtrl.push('MapsPage', {data: {current, markers: [me, current]}});
    }, err => {
      console.log('Error getting closest user', err)
    })
  }

You can see how it’s just like getting the closest User as we have done earlier.

Step 7 - Add buttons to Home Page

You probably noticed we have no way of calling those methods, let’s add the buttons to the home.ts then and make it happen!

home.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
  <div text-center class="gps-buttons">
    <button ion-button block margin-top (click)="findMyLocation()">
      Find my location
    </button>

    <button ion-button block margin-top (click)="getClosestUser()">
      Find closest user
    </button>

    <button ion-button block margin-top color="secondary" (click)="getAllStores()">
      Find all store
    </button>

    <button ion-button block margin-top color="secondary" (click)="getClosestStore()">
      Find closest store
    </button>
  </div>

Step 8 - Test your app

  1. Login at Back4App Website.
  2. Find your app and click on Dashboard > Core > Browser > User and create some users with location associated to them to allow the method getClosestUser to work.
  3. Run your app in a real device or in the browser to sign up and log in. Try every feature!

It’s done!

At this stage, you can use some features of ParseGeoPoint through Back4App!