Using the Google Maps Component

Using the Google Maps component in an Ionic app.

🚧

Important Note!

Note that the option of creating new apps with the Ionic framework was removed but we still support the projects that were created with it earlier.

Introduction

Appery.io provides a Google Map component. The main benefit of using Google Map is that you can simply drag it on the page, configure it via the properties panel like any other UI component, and then use it as the Google Maps API via JavaScript.

The following tutorials will show you how to use the Google Map component with directives such as Marker(s).

🚧

Important Note!

Note that the option of creating new apps with the Ionic framework was removed but we still support the projects that were created with it earlier.

Getting Started

📘

Google Maps API key

Don't forget to set up a Google Maps API key for yourself if you haven't already. It's required for the Google Maps component to work correctly in your app. Learn how to get your API key from this guide. And, be careful with API restrictions. (You can read about these here.)

Below you will find six independent sections with different features described. This way, you can complete only those ones you need, but there are some prep steps you must take before proceeding with any of the tutorials below:

  1. From the Apps page, perform: Create new app > Ionic AngularJS App (you can also use Bootstrap AngularJS App), select Blank, enter an app name and click Create. You’ll see a start page.
  2. To create the UI, drag&drop the Google Map component to the Screen1 page and define the two properties (Zoom = map.zoom, control = map.control) under the PROPERTIES tab. These will apply for all the apps described below.
  3. Function init() is also common for all the apps and should be defined with the following code from the start. Open the CODE tab and define it:
$scope.map = {
    control: {},
    zoom: 3,     
};

Showing User Location on the Map via Geolocation Service

First, let’s build an AngularJS app using the Geolocation service.

  1. The app UI will consist of:
  • The Google Map component:
    Select the Marker1 component (to do it, you may use breadcrumbs or the OUTLINE tab (open the components tree and then expand GoogleMap1) and define its properties like the following: Coords = *myPosition, options = myPosition.options.
  • The Button component (set the Width property to Block, Text = My Position, Color = balanced, and define ng-click as getMyPosition()).

The result:

1908

Google Maps component.

  1. To create the necessary services, you’ll use the Geolocation plug-in from Apache Cordova: Create New > From Plug-in > Apperyio Geolocation Service and click Import selected plugins. Three new Geolocation services and a .js file will appear under the Project tree.
  2. Then, create a new model called marker in Project > Model and define it.
1118

App model.

  1. Now, switch to Screen 1 > SCOPE and, under the Variables tab, add a new variable – myPosition (Type = marker).
  2. Then, make corrections to the existing code of the init() function, so that it looks like the following:
$scope.map = {
    control: {},
    zoom: 3,   
};
 
$scope.myPosition = {
    latitude: 0,
    longitude: 0,
    options: {
        visible: false,
        icon: "http://i.imgur.com/fDUI8bZ.png"
    }
};
  1. Now, add a new scope function – getMyPosition which will be called on the My Position button click. Click Edit, from the snippets drop-down list, select Invoke service and, for the service name, type Geolocation_currentPosition (you may also click Backspace and then + to autocomplete the service name):
1368

Invoking Geolocation_currentPosition service

  1. In the Mapping editor for success event, create the following mapping.
1169

Mapping.

  1. Click Save & Replace.
  2. Finally, add the next three code lines to this function:
$scope.myPosition.options.visible = true;
$scope.map.zoom = 10;
$scope.map.control.refresh($scope.myPosition);

Your final view of the getMyPosition() function shoud look as follows:

var requestData = {};
    /*CLICK TO EDIT MAPPING*/

// read more about using rest services: https://links.appery.io/ve-snippet-rest
Apperyio.get("Geolocation_currentPosition")(requestData).then(
function(success){ // success callback
    (function mapping2039(success, $scope){
        var myPosition_scope = $scope.myPosition;
        _.set(myPosition_scope, 'latitude', success.coords.latitude);
        _.set(myPosition_scope, 'longitude', success.coords.longitude);
        $scope.myPosition = myPosition_scope;
        /*CLICK TO EDIT MAPPING*/
    })(success, $scope);
    
$scope.myPosition.options.visible = true;
$scope.map.zoom = 10;
$scope.map.control.refresh($scope.myPosition);

},
function(error){ // callback to handle request error

},
function(notify){ // notify callback, can fire few times

});

Testing the app

508

Testing the app.

Troubleshooting

1127

If you encounter this issue, make sure that the Google Maps Platform billing is enabled. To use the Maps JavaScript API, add the API key to all API requests and enable billing for each of your projects. You can read more about it here.

Adding Multiple Markers

The steps below show you how to place markers and get extra info on them upon clicking.

In your project, open the DESIGN tab and define the next components in the following way:
The Google Map component:

  1. First, select a Marker or add one by clicking the + sign:
707

Adding markers.

  1. Set its properties: Coords = marker, id Key = marker.id, and ng-repeat = marker in customMarkers***.
  2. Then, click the + sign in green to add a Marker's Window component and select it.
770

Google Maps component.

  1. Under the PROPERTIES tab of the newly created GoogleMapWindow, click Edit for HTML, enter the following expression and save:
{{marker.title}}
  1. Now, mofify the Button component as the follows: Width = Block, Text = Place Markers, Color = balanced, and ng-click = placeMarkers().
  2. Now, add the Input component with ng-model aset to customLocations).
507

Adding a marker.

  1. Then, in SCOPE, make corrections to the existing code of the init() function, so that it looks like the following:
$scope.map = {
  control: {},
  zoom: 3,
};
$scope.customLocations = "Chicago, Los Angeles, San Francisco";
  1. Now, add another scope function placeMarkers with the following code:
var locations = $scope.customLocations.split(',');
 
for (var i = 0; i < locations.length; i++) {
    var requestData = {
        params: {
            address: locations[i].trim()
        }
    };
    
    Apperyio.get("ConvertAddress")(requestData).then(        
        function(success) {            
            var marker = {};
            marker.id = success.data.results[0].place_id;
            marker.latitude = success.data.results[0].geometry.location.lat;
            marker.longitude = success.data.results[0].geometry.location.lng;
            marker.title = success.data.results[0].formatted_address;
            
            $scope.customMarkers.push(marker); 
            if ($scope.customMarkers.length === locations.length) { //fit the map to bounds when the loop is over
                fitMarkers($scope.customMarkers);
            }
        },
        
        function(error) {
            alert("Error");
        });
}
  1. To make it work, you’ll have to add one more service, Google Geocoding service.
  2. In the App Builder: CREATE NEW > Service, type name ConvertAddress and click Create Service.
  3. In the Settings tab of the newly-created service, type the following URL:
https://maps.googleapis.com/maps/api/geocode/json

This is what it should look like:

972

Google Maps REST API.

  1. Go to the Request tab and add two parameters – address and sensor. Type a mock value for the address parameter (for example, Chicago) and false value for the sensor parameter.
1643

Service request.

  1. Switch to the Test tab and click Test. After the test finishes successfully, click Import as Response to fill the Response data.
  2. Then, create a new model called markers of Array type in Project > Model.
  3. Now, switch to Screen 1 > SCOPE and, under the Variables tab, add two variables – customMarkers (Type = markers) and customLocations (Type=string).
  4. Lastly, add one more function: fitMarkers(), add markers for Arguments, define its Type as Function, and insert the following:
var minLat = 90,
    minLng = 180,
    maxLat = -90,
    maxLng = -180;
 
for (var i = 0; i < markers.length; i++) { //find boundary coordinates
    if (markers[i].latitude < minLat) {
        minLat = markers[i].latitude;
    }
    if (markers[i].latitude > maxLat) {
        maxLat = markers[i].latitude;
    }
    if (markers[i].longitude < minLng) {
        minLng = markers[i].longitude;
    }
    if (markers[i].longitude > maxLng) {
        maxLng = markers[i].longitude;
    }
}
 
var googleMapInstance = $scope.map.control.getGMap(),
     sw = new google.maps.LatLng(minLat, maxLng),
     ne = new google.maps.LatLng(maxLat, minLng);

googleMapInstance.fitBounds(new google.maps.LatLngBounds(sw, ne));

You can save and test your app:

511

Testing the app.

Showing A Separate Window On A Click

The steps below demonstrate how you can manage different map events in your projects.

  1. In DESIGN view, add one more property to the Google Map component (events = map.events) on the PROPERTIES tab.
  2. Add the Google Map Window component by clicking the Window+ sign.
598

Google Maps component.

  1. Set its show property to singleWindow.show, Coords property – to singleWindow.coords, then click Edit for HTML,enter the following expression, and save:
{{singleWindow.title}}
  1. In SCOPE, under the Variables tab, add two new variables – dbMarkers and customLocations.

  2. Switch to the Functions tab and define the init() function as follows:

$scope.map = {
    control: {},
    zoom: 3,
    events: {
        click: mapClick
    }
};
$scope.singleWindow = {
    title: "",
    coords: {
        latitude: 0,
        longitude: 0
    },
    show: false
};
  1. Add one more function – mapClick() with map e, args as Arguments and Type = Function and provide it with the following code:
var coords = {
    latitude: args[0].latLng.lat(),
    longitude: args[0].latLng.lng()    
};
 
$scope.singleWindow = {
    title: coords.latitude.toFixed(2) + " lat, " + coords.longitude.toFixed(2) + " lng",
    coords: coords,
    show: true
};
 
//scope apply required because this event handler is outside of the angular domain
$scope.$apply();
518

Testing the app.

Adding Multiple Markers From Appery.io Database

The markers will be stored in the database so the first step is to create a database to store the markers.

Creating A Database

Before you start building the app, you must create a database and a collection. The app will retrieve the collection data, and markers will be added to the map based on it.

Create the Markers collection with the following structure:

486

Database.

📘

On the screenshot above, there is a sample Markers collection, stored in the MapDB database.

You may also choose to create a cdatabase collection from the sample MapDB (in this case, unpack the sample .zip file first) or do it manually.

Locate the database ID (see below):

1219

Database collection.

Building The App

The steps below will guide you how to get markers from the database and place them on the map.

In the project, go to DESIGN view and define the next UI components in the following way:
the Google Map component:

  1. First, delete the default Marker (to do it, you may use breadcrumbs or the OUTLINE tab (to open the components tree and then expand GoogleMap1).
  2. Then, add a Google Map Markers component by clicking the + sign and set its Models parameter to dbMarkers.
586

Adding a marker.

  1. Then, inside the Google Map Markers map area, click the + sign in green to add a Google Map Windows component, then, in PROPERTIES, click Edit for HTML, and enter the following expression:
This is {{title}}
654

Adding a Google Map window

Add the Button component (Block = True, Text = Get Markers from DB, Type = primary, and ng-click = getMarkersFromDB()).

507

Adding a marker.

4.Perform CREATE NEW > Database Service and select the database you need (MapDB, in this example), expand the Markers collection, and select the List service and confirm. Check the database id under MapDB_settings > database_id on the Project view.
5. Then, switch to Project > Model and create two new models: marker and markers defined as follows.

1823

App models.

  1. Now, in SCOPE, add a new variable: dbMarkers (Type = markers).
  2. After that, add another function – getMarkersFromDB(). Click Edit, then, from the snippets drop-down list, select Invoke service and, for the service name, type MapDB_Markers_list_service (you may also click Backspace and then + to autocomplete the service name).
  3. Then, in the Mapping editor, create Mapping, and add the next expression to the code:
1126

Mapping.

fitMarkers(dbMarkers_scope);

Your getMarkersFromDB() function should look like the following:

var requestData = {};

Apperyio.get("MapDB_Markers_list_service")(requestData).then(

    function(success) {

        var dbMarkers_scope = $scope["dbMarkers"];
        dbMarkers_scope = [];
        for (var i1 = 0, l1 = success.data.length; i1 < l1; i1++) {
            dbMarkers_scope[i1] = Apperyio.EntityAPI('markers.[i]');
            dbMarkers_scope[i1].latitude = success.data[i1].latitude;
            dbMarkers_scope[i1].longitude = success.data[i1].longitude;
            dbMarkers_scope[i1].id = success.data[i1]._id;
            dbMarkers_scope[i1].title = success.data[i1].name;
        }
        $scope["dbMarkers"] = dbMarkers_scope;
        fitMarkers(dbMarkers_scope);


    },
    function(error) {

    });
  1. Add the following code to the init() function:
$scope.dbMarkers = [];
  1. The last function to be added – fitMarkers (Arguments = markers, Type = Function) should be defined in the following way:
var minLat = 90,
    minLng = 180,
    maxLat = -90,
    maxLng = -180;
 
for (var i = 0; i < markers.length; i++) { //find boundary coordinates
    if (markers[i].latitude < minLat) {
        minLat = markers[i].latitude;
    }
    if (markers[i].latitude > maxLat) {
        maxLat = markers[i].latitude;
    }
    if (markers[i].longitude < minLng) {
        minLng = markers[i].longitude;
    }
    if (markers[i].longitude > maxLng) {
        maxLng = markers[i].longitude;
    }
}
 
var googleMapInstance = $scope.map.control.getGMap(),
    sw = new google.maps.LatLng(maxLat, minLng),
    ne = new google.maps.LatLng(minLat, maxLng);
 
googleMapInstance.fitBounds(new google.maps.LatLngBounds(sw, ne));

Testing the app:

504

Testing the app.

Showing Traffic Layer

The steps below will guide you in creating an app showing traffic on the map and working with native Google Maps API rather than with AngularJS .

  1. The app UI will consist of:
  • The Google Map component (for settings, see here).
  • The Button component (set the Block property to True, Text = Show Traffic, Type = success, and ng-click = showTraffic()).
504

Showing traffic layer.

  1. In SCOPE, add one more scope function: showTraffic() and insert this code when editing.
var trafficLayer = $scope.map.trafficLayer,
    googleMapInstance = $scope.map.instance;

if (!trafficLayer) {
    $scope.map.trafficLayer = trafficLayer = new google.maps.TrafficLayer();
}
if (!googleMapInstance) {
    $scope.map.instance = googleMapInstance = $scope.map.control.getGMap();
}

trafficLayer.setMap(googleMapInstance);

$scope.map.zoom = 10;
$scope.map.control.refresh({
    latitude: 40.7,
    longitude: -74
});

The function applies to the specified location (New York City), which may be changed according to your preferences:

$scope.map.control.refresh({
    latitude: 40.7,
    longitude: -74
});

Testing the app:

511

Testing the app.

Showing Directions

The steps below will show you how to create a route from point A to point B.

  1. In DESIGN, define the next three UI components in the following way:
  • The Google Map component (for settings, see here).
  • The Button component (Block = True, Text = Show Directions, Type = success, and ng-click = showDirections()).
  • Two Input components:
    For the first Input, define: Placeholder = From, ng-model = directions.from.
    For the second Input, define: Placeholder = To, ng-model = directions.to.
509

Showing directions.

  1. Now, switch to SCOPE and make corrections to the existing code of the init() function so that it looks like the following:
$scope.map = {
    control: {},
    zoom: 3,

};
$scope.directions = {
    from: "London",
    to: "Abu Dhabi"
};
  1. Add a new function – showDirections() with the following code:
var directionsService = $scope.map.directionsService,
    directionsDisplay = $scope.map.directionsDisplay,
    gmap = $scope.map.instance;
 
if (!directionsService) {
    $scope.map.directionsService = directionsService = new google.maps.DirectionsService();
    $scope.map.directionsDisplay = directionsDisplay = new google.maps.DirectionsRenderer();
}
if (!gmap) {
    $scope.map.instance = gmap = $scope.map.control.getGMap();
}
 
var request = {
    origin: $scope.directions.from,
    destination: $scope.directions.to,
    travelMode: google.maps.DirectionsTravelMode.DRIVING
};
directionsService.route(request, function(response, status) {
    directionsDisplay.setMap(gmap);
    if (status == google.maps.DirectionsStatus.OK) {
        directionsDisplay.setDirections(response);
    } else {
        alert("Directions query unsuccessful. Response status: " + status);
    }
});

When testing the app you'll get:

505

Testing the app.

Adding A Reset Function

When working with Google Maps, it’s can be handy to reset all the data attached to it. The function below resets all the features described above.

  1. Go to SCOPE and add a new function (Type = Function): reset() with the following code:
$scope.myPosition.options.visible = false;
$scope.customMarkers = [];
$scope.dbMarkers = [];
 
$scope.singleWindow = {
    title: "",
    coords: {
        latitude: 0,
        longitude: 0
    },
    show: false
};
 
if ($scope.map.trafficLayer) {
    $scope.map.trafficLayer.setMap(null);
}
 
if ($scope.map.control.refresh) {
    $scope.map.control.refresh();
}
 
if ($scope.map.directionsDisplay) {
    $scope.map.directionsDisplay.setMap(null);   
}

Then, you can call this function any time, for example, on a button click:

reset();

📘

Note

If you are adding a Google Map component to Modal screen, add an attribute ng-if = true to the component.

Testing the App

You are now ready to test the app. Click the Test button in the App Builder to launch the app in the browser.