Hands On

Display an Interactive HERE Map in an Ionic Framework Application

By Nic Raboy | 12 February 2019

Back when I first started at HERE I had written a tutorial titled, Display HERE Maps within your Angular Web Application. In fact it was my first official tutorial since starting and since then I’ve received several similar requests around it. One popular request has been around taking the Angular web application and making it compatible with Ionic Framework.

In this tutorial we’re going to see how to build a progressive web application (PWA) using Ionic Framework that can be deployed on the web or on mobile devices running Android or iOS.

Take the following animated image of what we plan to accomplish:

here-maps-ionic-framework

As you can see, we have an interactive map available in both a web browser and on an Android device. This is the same application with the same code, running on both platforms. While we’re only showing an interactive map, it opens the door to further possibilities with the HERE JavaScript SDK.

Start a New Ionic Framework Project with the Ionic CLI

The first step towards being successful with this tutorial is to create a new project. We’re going to be using the Ionic CLI and we’re going to be building an Ionic 3.x application that uses Angular. Other versions of Ionic Framework will likely have different setup requirements.

Assuming you have the Ionic CLI installed, execute the following command:

ionic start HereMapProject blank

The above command will create a blank project. While we won’t be using any Ionic plugins or third-party Angular dependencies, we will need to include some libraries to make use of HERE in our application.

Open the project’s src/index.html and include the following HERE JavaScript SDK dependencies:

<script src="https://js.api.here.com/v3/3.0/mapsjs-core.js" type="text/javascript" charset="utf-8"></script>
<script src="https://js.api.here.com/v3/3.0/mapsjs-service.js" type="text/javascript" charset="utf-8"></script>
<script src="https://js.api.here.com/v3/3.0/mapsjs-mapevents.js" type="text/javascript" charset="utf-8"></script>

These libraries should be included within the <body> tags, above the other libraries defined by the Ionic CLI. To get clarity of what our finished src/index.html file should look like, see the following:

<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
    <meta charset="UTF-8">
    <title>HERE Map Example</title>
    <meta name="viewport" content="viewport-fit=cover, 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">
    <meta name="apple-mobile-web-app-capable" content="yes">
    <meta name="apple-mobile-web-app-status-bar-style" content="black">
    <script src="cordova.js"></script>
    <link href="build/main.css" rel="stylesheet">
</head>
<body>
    <ion-app></ion-app>
    <script src="https://js.api.here.com/v3/3.0/mapsjs-core.js" type="text/javascript" charset="utf-8"></script>
    <script src="https://js.api.here.com/v3/3.0/mapsjs-service.js" type="text/javascript" charset="utf-8"></script>
    <script src="https://js.api.here.com/v3/3.0/mapsjs-mapevents.js" type="text/javascript" charset="utf-8"></script>
    <script src="build/polyfills.js"></script>
    <script src="build/vendor.js"></script>
    <script src="build/main.js"></script>
</body>
</html>

Before proceeding to the next development steps, now would be a good opportunity to create a HERE developer account and obtain your application tokens. You’ll need both an app id and an app code for JavaScript to be able to use any of the HERE APIs.

Creating a HERE Map Component with Angular and Ionic Framework

Now that we have a basic project created for Ionic Framework, we need to create an Angular component to represent our HERE map. As seen in my previous tutorial, there are several ways to accomplish this in Angular, but for us, we should probably create an actual component that can be reused.

From the Ionic CLI, execute the following:

ionic generate component here-map

The above command will create an Angular component, configured for Ionic Framework. Eventually we’ll be able to use <here-map> throughout the pages of our application.

Open the project’s src/components/here-map/here-map.html file and include the following:

<div #map style="width: 100%; height: 100%"></div>

The above line will act as a placeholder for our interactive map. We are giving it full height and width so that way it scales to the parent dimensions found in each of the pages that you create. The #map attribute will allow us to find it in our TypeScript code.

Open the project’s src/components/here-map/here-map.ts file and include the following TypeScript logic:

import { Component, OnInit, ViewChild, ElementRef, Input } from '@angular/core';

declare var H: any;

@Component({
    selector: 'here-map',
    templateUrl: 'here-map.html'
})
export class HereMapComponent implements OnInit {

    @ViewChild("map")
    public mapElement: ElementRef;

    @Input()
    public appId: any;

    @Input()
    public appCode: any;

    @Input()
    public lat: any;

    @Input()
    public lng: any;

    public constructor() { }

    public ngOnInit() { }

    public ngAfterViewInit() {
        let platform = new H.service.Platform({
            "app_id": this.appId,
            "app_code": this.appCode
        });
        let defaultLayers = platform.createDefaultLayers();
        let map = new H.Map(
            this.mapElement.nativeElement,
            defaultLayers.normal.map,
            {
                zoom: 10,
                center: { lat: this.lat, lng: this.lng }
            }
        );
        let behavior = new H.mapevents.Behavior(new H.mapevents.MapEvents(map));
    }

}

If you think the above TypeScript looks familiar, it is because I took it exactly from the previous Angular tutorial that I had written. As a refresher, we’ll walk through it again to explain what everything means.

First you’ll notice this line:

declare var H: any;

Because our JavaScript SDK doesn’t have any TypeScript type definitions, we need to declare the class we wish to use so we don’t get transpiler errors. Basically we’re saying to ignore the fact that H won’t be recognized in TypeScript.

Remember that #map we had in the HTML? The following line will allow us to gain access to it:

@ViewChild("map")
public mapElement: ElementRef;

The ViewChild matches the name, but the variable can be whatever you want. Each of the Input annotations will reflect possible tag attributes to be passed when we try to use the <here-map> tag.

Because the map will render after our view has finished loading, we have to do all of our logic in the ngAfterViewInit method. In this method we configure the platform and display the map based on the information supplied as tag attributes.

Before we can start using our new component, we need to wire it up to Ionic Framework. As of now it is only an Angular component.

Open the project’s src/app/app.module.ts file and include the following:

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 { ComponentsModule } from "../components/components.module";

import { MyApp } from './app.component';
import { HomePage } from '../pages/home/home';

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

Notice in the above code that we have imported our ComponentsModule and then added it to the imports array of the @NgModule block. That is the only change we’ve made to this file.

Use the Interactive HERE Map Component within Ionic Framework Pages

With the map component under control, now we can start using it in the pages of our application. We’re working with a blank project so we’ll have a single page to work with. Your project may vary and you’re definitely not limited to just a single page.

Open the project’s src/pages/home/home.html file and include the following:

<ion-header>
    <ion-navbar>
        <ion-title>
            HERE Maps Example
        </ion-title>
    </ion-navbar>
</ion-header>

<ion-content>
    <here-map appId="APP-ID-HERE" appCode="APP-CODE-HERE" lat="37.7397" lng="-121.4252"></here-map>
</ion-content>

Take note of the <here-map> tag that we’re using. In this tag we’re passing our attributes which we’re catching on the other end. Just make sure you swap your app id and app code rather than use my placeholder values.

Conclusion

You just saw how to include an interactive HERE map in an Ionic Framework progressive web application (PWA). Out of the box you should be able to build for the web with the Ionic CLI, but if you wish to build for Android or iOS, you’ll need to have Apache Cordova and the various Apache Cordova requirements met. However, you won’t have to change any of your code once Apache Cordova is configured.

For this example we were using the HERE JavaScript SDK rather than the HERE Android SDK or HERE iOS SDK.