In this Angular 8 tutorial, we will be building a realtime blood donor app based on location tracking. Set the donor location to Firebase realtime database that automatically updated and seen by other users as real-time Google maps markers. The other users that see the blood donor markers on Google maps based on near to their device or computer location. So, they can choose and contact the desire blood donor then contact it.
Table of Contents:
- Prerequisites
- Setup Google Maps API Key
- Set up Firebase Realtime Database
- Create a New Angular 8 Web App
- Install Google Firebase SDK
- Create Angular Component and Routing
- Display Google Maps
- Get Donor List from Firebase Realtime Database
- Display Donor Position to Google Maps
- Add a New Donor Data using Angular Material
- Run and Test Angular 8 Google Maps Firebase Realtime Blood Donor App
Simply as that the flow of the Angular 8 Google Map Location Firebase realtime donor app.
Prerequisites
As we mention in the first paragraph of this tutorial, this Angular 8 web app involves Google Map, Browser Location, and Firebase Realtime Database. So, the following tools, frameworks, libraries, and modules are required for this tutorial achievement:
- Node.js
- Angular 8
- Google Maps Javascript API
- Google Maps API Key
- Firebase Realtime Database
- Firebase Javascript Module
- Terminal or Node Command Line
- Text Editor or IDE
As usual, we have to make sure the Node.js installed correctly before going to the main steps. Type this command in the terminal or command line to check the installed Node.js and NPM.
node -v
v10.15.1
npm -v
6.11.2
If there's no Node.js and NPM installed, go to the Node.js official site then download and install it.
Setup Google Maps API Key
To use Google Maps Javascript API we need a Google Maps API key. The Google Maps JavaScript API lets you customize maps with your own content and imagery for display on web pages and mobile devices. The Maps JavaScript API features four basic map types (roadmap, satellite, hybrid, and terrain) which you can modify using layers and styles, controls and events, and various services and libraries.
Next, open your browser the go to the Google Developer Console. You will be taken to this Google Developer Console page.
Just scroll the default opened projects then it will take to this dialog.
Click the "New Project" button then it will take to this New Google Project page.
Fill the project name and leave other fields as default then click the "Create" button and it will take to the Google Developer Console home page with default opened project. Select again the project then choose the newly created Angular Maps project and click the "OK" button. It will take to the Angular Maps project dashboard without any APIs enabled.
Click the "Enable API" button then it will take to this Google APIs library page.
Find and choose Maps Javascript API then it will take to this Maps Javascript API page.
Just click on the "Enable" button then it will take back to the Maps Javascript API dashboard.
Click on Credentials link then it will take to the Credentials page.
Click on "+ Create Credentials" link then choose "API KEY" and it will take to the API KEY dialog. Copy and paste the newly created API KEY to your Notepad or Text Editor for using in the Angular app.
Set up Firebase Realtime Database
Next, we will set up or create a new Google Firebase project that can use the realtime database. Just open your browser then go to Google Firebase Console and it will take to this page.
From that page, click "+" add project button to create a Google Firebase project then it will be redirected to this page.
Type the previously created Google APIs project then choose the existing Google APIs project and click the "Continue" button.
This time, choose to not add Firebase analytics for now then click the "Add Firebase" button. And now, the Firebase will be added to the Angular Maps project.
Click the "Continue" button then it will take to the Firebase Angular Maps project dashboard.
Click the "Database" menu then it will take to the Firebase Database dashboard.
Scroll down and find "Or Choose Realtime Database" then click on the "Create Database" button. Next, it will take to the "Security rules for Realtime Database" dialog.
Choose "Start in test mode" radio button then click on the "Enable" button and it will take to the "Realtime Database" dashboard. Now, the Google Firebase realtime database is ready to use with your Angular Maps web app.
Create a New Angular 8 Web App
In the prerequisites step, we have checked the Node.js and NPM version. Now, we have to install or check the Angular CLI version. The Angular CLI is a tool to initialize, develop, scaffold and maintain Angular applications. From the Terminal or Node Command Line, type this command to install or update the Angular CLI.
sudo npm install -g @angular/cli
Now, we have the latest version of Angular when this example was written.
_ _ ____ _ ___
/ \ _ __ __ _ _ _| | __ _ _ __ / ___| | |_ _|
/ ? \ | '_ \ / _` | | | | |/ _` | '__| | | | | | |
/ ___ \| | | | (_| | |_| | | (_| | | | |___| |___ | |
/_/ \_\_| |_|\__, |\__,_|_|\__,_|_| \____|_____|___|
|___/
Angular CLI: 8.3.2
Node: 10.15.1
OS: darwin x64
Angular:
...
Package Version
------------------------------------------------------
@angular-devkit/architect 0.803.2
@angular-devkit/core 8.3.2
@angular-devkit/schematics 8.3.2
@schematics/angular 8.3.2
@schematics/update 0.803.2
rxjs 6.4.0
Next, create an Angular 8 application for this Google Maps Firebase Realtime Blood Donor App by typing this command.
ng new angular-maps
Answer all questions like below which we will skip Angular Routing and use SCSS as a stylesheet.
? Would you like to add Angular routing? No
? Which stylesheet format would you like to use? SCSS [ https://sass-lang.com/documentation/syntax#scss ]
Next, to sanitize the newly created Angular 8 project go to that project folder then run the Angular application.
cd ./angular-maps
ng serve
You will this page or view when you open "http://localhost:4200/" in your browser which means the Angular 8 is ready to go.
Install Google Firebase SDK
We will use Google Firebase Javascript SDK for accessing Firebase Realtime Database. For that, type this command to install the module.
npm install --save firebase
Next, register the Firebase SDK module in the Angular Maps app by open and edit this file `src/app/app.component.ts` then add these imports of Firebase.
import * as firebase from 'firebase';
Declare a constant variable for holds Firebase setting before `@Component` that contain the configuration variable for accessing Firebase using apiKey, authDomain, databaseURL, projectId, storageBucket.
const config = {
apiKey: 'YOUR_APIKEY',
authDomain: 'YOUR_AUTH_DOMAIN',
databaseURL: 'YOUR_DATABASE_URL',
projectId: 'YOUR_PROJECT_ID',
storageBucket: 'YOUR_STORAGE_BUCKET',
};
You can find or get those configuration parameters by click on the settings (gear button) -> Project Settings to get web API key and Project ID. Click Develop -> Authentication then scrolls to Authorized domain to get authDomain value. In order to get the value of storageBucket, you have to enable or start a Storage by going to Develop -> Storage. Next, initialize Firebase configuration settings inside Angular constructor.
constructor() {
firebase.initializeApp(config);
}
Now, the Firebase realtime database is ready to use.
Create Angular Component and Routing
We will display the Google maps and add a new donor in the new Angular components. For that, generate component using Angular schematics.
ng g component donor-list
ng g component add-donor
Because in the first Angular creation not including the Routing, we have to add it manually. Open and edit `src/app/app.module.ts` then add this import of Angular RouterModule and Router.
import { RouterModule, Routes } from '@angular/router';
Add a constant variable after the imports for the routes to the new Angular component.
const appRoutes: Routes = [
{ path: 'donor-list', component: DonorListComponent },
{ path: 'add-donor/:lat/:lng', component: AddDonorComponent },
{ path: '',
redirectTo: '/donor-list',
pathMatch: 'full'
}
];
Add the Angular RouterModule to the @NgModule imports.
imports: [
...
RouterModule.forRoot(
appRoutes
)
],
As you see, the newly created components already registered in the Angular AppModule.
Display Google Maps
Now, we will display a Google Maps in the Angular component (donor-list) template using Google Maps Javascript SDK. Before that, we need to load the Google Maps Javascript SDK first by open and edit `src/index.html` then add this Script loader before the closing of </body> tag.
<body>
<app-root></app-root>
<script src="http://maps.googleapis.com/maps/api/js?key=AIzaSyCeUZ4BzsoVCSMnnGdNUQxDlIMSxEQhmLU"></script>
</body>
Next, open and edit `src/app/donor-list/donor-list.component.html` then replace all HTML tags with this tag that represent the Google Maps.
<div #map id="map"></div>
Open and edit `src/app/donor-list/donor-list.component.ts` then modify the @angular/core import to add ViewChild and ElementRef.
import { Component, OnInit, ViewChild, ElementRef } from '@angular/core';
Declare the basic required Google maps variables (map, marker, options) before the Angular @Component.
declare var google: any;
let map: any;
let marker: any;
const options = {
enableHighAccuracy: true,
timeout: 5000,
maximumAge: 0
};
let infowindow: any;
const iconBase = 'http://maps.google.com/mapfiles/ms/icons/';
Load map element, after the title variable.
@ViewChild('map', {static: false}) mapElement: ElementRef;
Create a function to load Google Maps and set a default marker of the current browser location.
initMap() {
navigator.geolocation.getCurrentPosition((location) => {
map = new google.maps.Map(this.mapElement.nativeElement, {
center: { lat: location.coords.latitude, lng: location.coords.longitude },
zoom: 15
});
infowindow = new google.maps.InfoWindow();
marker = new google.maps.Marker({
position: { lat: location.coords.latitude, lng: location.coords.longitude },
map,
title: 'Click to zoom',
icon: iconBase + 'blue-dot.png'
});
map.addListener('center_changed', () => {
window.setTimeout(() => {
map.panTo(marker.getPosition());
}, 3000);
});
marker.addListener('click', (event: any) => {
infowindow.setPosition(event.latLng);
infowindow.setContent('<h2>Yes, I wanna be a donor!</h2>' +
'<h3><a href="/add-donor/' + marker.getPosition().lat() + '/' + marker.getPosition().lng() + '">Register Here</a></h3>');
infowindow.open(map, marker);
});
}, (error) => {
console.log(error);
}, options);
}
Call that function inside Angular constructor.
constructor() {
this.initMap();
}
Now, the Google maps are displayed in the Angular page and ready to populate with a lot of markers that load from the Firebase realtime database. The current user location will be marked as a blue-dot icon.
Get Donor List from Firebase Realtime Database
Let's get back to the Firebase Realtime Database. We will get the list of Donor data from the Firebase Realtime Database. Still on `src/app/donor-list/donor-list.component.ts` then add this import of the Firebase.
import * as firebase from 'firebase';
Next, add this export constant function before the Angular @Component to extract the Firebase Realtime Database response to the Angular array.
export const snapshotToArray = (snapshot: any) => {
const returnArr = [];
snapshot.forEach((childSnapshot: any) => {
const item = childSnapshot.val();
item.key = childSnapshot.key;
returnArr.push(item);
});
return returnArr;
};
Add the variables after @ViewChild variable to holds response data from Firebase realtime database.
donors = [];
Create a constructor after the variables to implement the Firebase realtime database. So, the data from Firebase automatically fetched on every value changes in Firebase realtime database side.
constructor() {
firebase.database().ref('donors/').on('value', resp => {
this.donors = [];
this.donors = snapshotToArray(resp);
});
this.initMap();
}
The received data should contain the name, phone, email, and the coords.
Display Donor Position to Google Maps
After we have got donors data from the Firebase realtime database, we will display that data to Google Maps as the markers. Still, on `src/app/donor-list/donor-list.component.ts` iterate the donors' array to set the marker of the donors to the Google Maps.
constructor() {
firebase.database().ref('donors/').on('value', resp => {
this.donors = [];
this.donors = snapshotToArray(resp);
for (const donor of this.donors) {
this.createMarkers(donor);
}
});
this.initMap();
}
Add a new function to create markers that iterated from the donors' array.
createMarkers(place: any) {
const latitude = parseFloat(place.coords.latitude);
const longitude = parseFloat(place.coords.longitude);
const donorMarker = new google.maps.Marker({
map,
position: { lat: latitude, lng: longitude },
icon: iconBase + 'green-dot.png'
});
google.maps.event.addListener(donorMarker, 'click', function() {
infowindow.setContent('<h3>' + place.name + '</h3><p>Phone number: ' + place.phone + '<br>Email: ' + place.email + '</p>');
infowindow.open(map, this);
});
}
Now, we have displayed the donors as green-dot markers.
Add a New Donor Data using Angular Material
Next, we will use another newly created Angular component for add new donor data. For add data form, we will use Angular Material and Reactive Form. For that, add Angular Material to this project using schematics.
ng add @angular/material
Open and edit `src/app/app.module.ts` then add these imports of BrowserAnimationModule, the required Angular Material components, and Angular ReactiveForm.
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import {
MatInputModule,
MatPaginatorModule,
MatProgressSpinnerModule,
MatSortModule,
MatTableModule,
MatIconModule,
MatButtonModule,
MatCardModule,
MatFormFieldModule } from '@angular/material';
Add them into @NgModule imports.
imports: [
...
FormsModule,
ReactiveFormsModule,
BrowserAnimationsModule,
MatInputModule,
MatTableModule,
MatPaginatorModule,
MatSortModule,
MatProgressSpinnerModule,
MatIconModule,
MatButtonModule,
MatCardModule,
MatFormFieldModule,
...
],
Next, open and edit `src/app/add-donor/add-donor.component.ts` then add these imports of Angular ActivatedRoute, Router, FormControl, FormGroupDirective, FormBuilder, FormGroup, NgForm, Validators, ErrorStateMatcher, and Firebase.
import { ActivatedRoute, Router } from '@angular/router';
import { FormControl, FormGroupDirective, FormBuilder, FormGroup, NgForm, Validators } from '@angular/forms';
import { ErrorStateMatcher } from '@angular/material/core';
import * as firebase from 'firebase';
Add a new export class for handling the error of each FormControl after the imports.
export class MyErrorStateMatcher implements ErrorStateMatcher {
isErrorState(control: FormControl | null, form: FormGroupDirective | NgForm | null): boolean {
const isSubmitted = form && form.submitted;
return !!(control && control.invalid && (control.dirty || control.touched || isSubmitted));
}
}
Add the required variables of donor FormGroup, name, phone, email, lat, lng, and Firebase database reference.
donorForm: FormGroup;
name: string='';
phone: string='';
email: string='';
lat = '';
lng = '';
ref = firebase.database().ref('donors/');
Inject the previously imported modules to the constructor and fill the constructor body with data from the previous page and set to LAT and LNG variables.
constructor(private route: ActivatedRoute, private router: Router, private formBuilder: FormBuilder) {
this.lat = this.route.snapshot.paramMap.get('lat');
this.lng = this.route.snapshot.paramMap.get('lng');
}
Initialize each of the FormControl in the FormGroup including the validations inside NgOnInit function.
ngOnInit() {
this.donorForm = this.formBuilder.group({
'name' : [null, Validators.required],
'phone' : [null, Validators.required],
'email' : [null, Validators.required]
});
}
Add a function for handling the submitted form than send the form controls values to the Firebase Realtime Database.
onFormSubmit(form: any) {
const donor = form;
donor.coords = { latitude: this.lat, longitude: this.lng };
const newDonor = firebase.database().ref('donors/').push();
newDonor.set(donor);
this.router.navigate(['/']);
}
After form submitted and data sent to Firebase realtime database, it will return to the previous Google Maps page.
Run and Test Angular 8 Google Maps Firebase Realtime Blood Donor App
To run this Angular 8 Google Maps Firebase Realtime Blood Donor App, simply type this Angular command.
ng serve
Now, you can go to `localhost:4200` using your browser then you see the maps. For demo purpose, you use a single browser then change the geolocation of the browser. You can watch the full demo here.
That it's, the Angular 8 Google Maps Firebase Realtime Blood Donor App. You can get the full source code from our GitHub.
If you don’t want to waste your time design your own front-end or your budget to spend by hiring a web designer then Angular Templates is the best place to go. So, speed up your front-end web development with premium Angular templates. Choose your template for your front-end project here.
That just the basic. If you need more deep learning about MEAN Stack, Angular, and Node.js, you can take the following cheap course:
- Master en JavaScript: Aprender JS, jQuery, Angular 8, NodeJS
- Angular 8 - Complete Essential Guide
- Learn Angular 8 by creating a simple Full Stack Web App
- Angular 5 Bootcamp FastTrack
- Angular 6 - Soft & Sweet
- Angular 6 with TypeScript
Thanks!