It is incredibly easy to include a map within your web application using the HERE JavaScript API as long as you’re using vanilla JavaScript, but how do you include a map in your application if you’re using one of the more popular frameworks like Angular? Frameworks like Angular typically have a transpile process and a specific way to do business.
We’re going to see numerous approaches to including a map in your Angular application using the HERE JavaScript API and how easy it is to do so in comparison to vanilla JavaScript.
The goal of this project will be to render a map that looks like the following:
While it is a basic project, we’re going to see two different approaches towards solving the problem with Angular.
The Requirements
There are a few requirements that must be met prior to developing a web application with Angular and displaying a map on the screen.
- The Angular CLI must be installed and configured.
- A HERE developer account must have been registered with an App ID and App Code available.
If you’re new to Angular, the Angular CLI can be obtained through the Node Package Manager (NPM). A HERE developer account can be created for free from the Developer Portal.
Creating a New Angular Project with the Angular CLI
With the development prerequisites in place, the next logical step is to create a fresh project to work with. Somewhere on your computer, execute the following command from your command line:
ng new here-project
The above command will create a new project directory with the appropriate Angular boilerplate files.
With the project created, the appropriate JavaScript libraries must be loaded to work with maps and the other location services.
Open the project’s src/index.html file and include the following:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>HERE with Angular</title>
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
</head>
<body>
<app-root></app-root>
<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>
</body>
</html>
In the above HTML markup, notice that the scripts are loaded before the
<body>
tag closes. This will eliminate the risk of any render blocking JavaScript.
At this point in time, we can start developing an application that includes a map.
Including a HERE Map within your Angular Component
The first approach towards including a map component in our application is convenient, but probably only for the short term and not at scale. Neither approach is wrong, but it is a good idea to look at both approaches.
Open the project’s src/app/app.component.html file and include the following:
<div #map style="width: 1280px; height: 768px"></div>
If you’ve read the official documentation for the HERE API with JavaScript, the above line might look loosely familiar. Basically it is going to act as a container for the map component. However, we are no longer working with an
id
and instead are working with a #map
. The #map
acts as an Angular template variable which is more appropriate when trying to work directly with the DOM rather than using data bindings.
Now open the project’s src/app/app.component.ts file so we can add our TypeScript logic that performs the bulk of our work:
import { Component, OnInit, ViewChild, ElementRef } from '@angular/core';
declare var H: any;
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
private platform: any;
@ViewChild("map")
public mapElement: ElementRef;
public constructor() {
this.platform = new H.service.Platform({
"app_id": "APP-ID-HERE",
"app_code": "APP-CODE-HERE"
});
}
public ngOnInit() { }
public ngAfterViewInit() {
let defaultLayers = this.platform.createDefaultLayers();
let map = new H.Map(
this.mapElement.nativeElement,
defaultLayers.normal.map,
{
zoom: 10,
center: { lat: 37.7397, lng: -121.4252 }
}
);
}
}
In the
AppComponent
class we are creating a ViewChild
variable using the #map
variable name and assigning it to a TypeScript variable that we can continue to use.
In the
constructor
method we are initializing the HERE platform service using the App ID and App Code that we obtain through our developer account. The constructor
method is triggered when the component is created.
This takes us to the
ngAfterViewInit
method which is triggered after the HTML view is initialized. Because we are working with a UI component, it is not a good idea to run any map-related code until we’re sure the UI has rendered. When we initialize the map, we use the mapElement
variable that is linked to the HTML.
You can test the application by executing the following from your command line:
ng serve
In this scenario, everything is more or less hard-coded and is not really able to be recycled within the application. The second approach is going to change this.
Developing a Map Component with Custom Input Attributes
The next approach is to create a component to strictly maintain the map and nothing else. Within this component, we can define input attributes so values can be defined via HTML attributes and not directly in the TypeScript.
With the command line within your project’s path, execute the following command:
ng g component here-map
The above command will create a new Angular component and link it within the project’s src/app/app.module.ts file.
Open the project’s src/app/here-map/here-map.component.ts file so we can define the core logic:
import { Component, OnInit, ViewChild, ElementRef, Input } from '@angular/core';
declare var H: any;
@Component({
selector: 'here-map',
templateUrl: './here-map.component.html',
styleUrls: ['./here-map.component.css']
})
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;
@Input()
public width: any;
@Input()
public height: 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 }
}
);
}
}
The above code is similar to what we’ve already seen, but not quite the same. We are creating a reference to a
#map
variable within our HTML, but we are also creating references to possible inputs. After the view initializes, the input values are used to initialize the map.
Let’s look at the HTML markup that pairs with our TypeScript. Open the project’s src/app/here-map/here-map.component.html file and include the following:
<div #map [style.width]="width" [style.height]="height"></div>
The above HTML also looks similar to what we’ve already seen. However, this time we are binding the public
width
and height
variables from the TypeScript to the styling of the element. Eventually, these width
and height
values will be defined by the user.
Now let’s make use of our new Angular component. Going back to the project’s src/app/app.component.html file, wipe out what’s currently in there and include the following:
<here-map appId="APP-ID-HERE" appCode="APP-CODE-HERE" lat="37.7397" lng="-121.4252" width="100%" height="835px"></here-map>
We’re going to break down what is happening in the above custom HTML tag. The
here-map
name is derived from our TypeScript file. In the TypeScript file, you’ll notice that our selector
is actuallyhere-map
All the attributes on this custom tag are actually the inputs that we defined in the TypeScript file.
By creating a component for our map, I personally think it becomes easier to manage in Angular.
Conclusion
You just saw how to use maps in your web application built with Angular and the HERE Maps API for JavaScript. Generally, the setup for JavaScript UI components require a bit more configuration than vanilla JavaScript, but as you’ve seen, it isn’t too bad.
With custom tag attributes, you could link up other aspects of the API to include markers or something else, all of which we’ll explore in future Angular tutorials.
1 Comments
This is really a worthy and wonderful blog to read and further more tips tyre insurance, bmw used car warranty
ReplyDelete