This post is a continuation of my previous post titled: Indoor Mapping with Google Maps API and GeoJSON.
In the previous post I have described how to create an indoor mapping web app using Google Maps API in pure JavaScript. In this post we will see how to convert that application to use Angular framework and TypeScript instead of JavaScript. Currently, only a part of the whole application is converted which include the following:
- Base map using Google Map
- GeoJSON data imported without level switch control and Information Bar.
So, let’s start!
1. Creating a new Angular project
I have used the Angular CLI to create a new Angular project. Angular CLI is a command line interface tool which can do much more that creating a project. This include, adding files to project, testing, bundling, deployment, etc.
To install Angular CLI, use the command:
npm install -g @angular/cliPr-requirements: Node 6.9+ and npm 3+
To create a new project, run the command:
ng new indoor-map-agmWhere “indoor-map-agm” is the name of our project.
Wait for while to complete process.
2. Installing Angular Google Maps (AGM)
Angular Google Maps (AGM) is a package which provides angular components and directives to implement Google Maps API in Angular 2 and above. In order to use AGM, we have to first install it into our project.
AGM can be installed using npm:
cd indoor-map-agm npm install @agm/core --save3. Setting Up app.module, app.component and Service
We have to import the AgmCoreModule in the app.module.ts and set it up within the @NgModule decorator. Also, it is important to place our Google Maps API key in the @NgModule.
After performing these changes, our app.module.ts now look like this:
import { BrowserModule } from '@angular/platform-browser'; import { NgModule, ApplicationRef } from '@angular/core'; import { CommonModule } from '@angular/common'; import { FormsModule } from '@angular/forms'; import { AppComponent } from './app.component'; import { HttpModule } from '@angular/http'; import { AgmCoreModule } from '@agm/core'; @NgModule({ declarations: [ AppComponent ], imports: [ BrowserModule, CommonModule, FormsModule, HttpModule, AgmCoreModule.forRoot({ apiKey: 'AIzaSyCuF0jO6w-aCgx7P28epp7zKGbNJwjlw6g' }) ], providers: [], bootstrap: [AppComponent] }) export class AppModule { }Our app.component.ts is given below:
import { Component, OnInit } from '@angular/core'; import { IndoorDataService } from "./indoordata.service"; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'], providers: [IndoorDataService] }) export class AppComponent implements OnInit { title: string = 'Mapping with Angular'; lat: number = 12.992634899999999; lng: number = 77.71721695; zoom: number = 20; geoJsonObject: Object; constructor(private _indoorDataService: IndoorDataService) {} // function to consume IndoorDataService observable getGeoJSON(): void { this._indoorDataService.getGeoJson() .subscribe(resGeoJsonData => this.geoJsonObject = resGeoJsonData); } // on init lifecycle hook // We get the GeoJSON here ngOnInit() : void { this.getGeoJSON(); } styleFunc(feature) { // get level - 0/1 var level = feature.getProperty('level'); var color = 'green'; // only show level one features var visibility = level == 1 ? true : false; return { // icon for point geometry(in this case - doors) icon: 'assets/images/door.png', // set fill color for polygon features fillColor: color, // stroke color for polygons strokeColor: color, strokeWeight: 1, // make layer 1 features visible visible: visibility }; } }Everything except the highlighted lines are self explanatory as we have already done it in the previous post. The highlighted code is concerned with importing and consuming the Angular Service which is responsible for fetching the GeoJSON file from the server. A detailed explanation of Service and Observables can be seen in this video.
As we can see, we have imported the IndoorDataService from indoordata.service.ts. The content of indoordata.service.ts is shown below:
import { Injectable } from '@angular/core'; import { Http, Response } from '@angular/http'; import 'rxjs/add/operator/map'; @Injectable() export class IndoorDataService { // location of GeoJSON file in server private _url: string = 'assets/pg.json'; constructor(private _http: Http) {} // fetch the file and parse the result as JSON getGeoJson() { return this._http.get(this._url) .map((response: Response) => response.json()); } }4. HTML and CSS
As declared in the app.component.ts file’s @Component decorator, we have two separate file which include the HTML and CSS respectivley for rendering the map.
The content of the app.component.html is shown below:
<!-- this creates a google map on the page with the given lat/lng from --> <!-- the component as the initial center of the map: --> <agm-map [latitude]="lat" [longitude]="lng" [zoom]="zoom"> <agm-data-layer *ngIf="geoJsonObject" [geoJson]="geoJsonObject" (layerClick)="clicked($event)" [style]="styleFunc" > </agm-data-layer> </agm-map>This agm-map component is provided by AGM and it takes the inputs longitude, latitude and zoom. Also the agm-data-layer component is used to import the GeoJSON to map. The *ngIf directive check if the geoJsonObject is not null (whether it is loaded or not). This is important as, if not used, the feature style wont apply correctly.
The CSS file contain minimal rules to set the height of the map:
html, body { height: 100%; margin: 0; padding: 0; } app-root, agm-map { height: 500px; }5. Running the Application
Finally to run the app and see our map in action, use the command:
ng serve --openThe complete code is available here: github
3 comments
Hi, your github link is broken. Could you restore it?
Sorry. It is restored now!
Thank you very much. Your tuto is so usefull 😀