Skip to main content

Overview

Rodando Driver uses the Google Maps JavaScript API with the Places library for map display and location services. The application dynamically loads the Google Maps script and configures it through the BaseMapComponent.

Prerequisites

Before configuring Google Maps in your application, you need:
  • A Google Cloud Platform account
  • A project with billing enabled
  • Google Maps JavaScript API enabled
  • Places API enabled
  • A valid API key

Google Cloud Console Setup

1

Create a Google Cloud Project

  1. Go to Google Cloud Console
  2. Click Select a projectNew Project
  3. Enter a project name (e.g., “Rodando Driver”)
  4. Click Create
2

Enable Required APIs

Navigate to APIs & ServicesLibrary and enable:
  • Maps JavaScript API - For displaying maps
  • Places API - For location autocomplete and place details
  • Geocoding API (optional) - For address lookup
  • Directions API (optional) - For route planning
Click on each API and press the Enable button.
3

Create an API Key

  1. Go to APIs & ServicesCredentials
  2. Click + Create CredentialsAPI key
  3. Copy the generated API key
  4. Click Restrict Key to configure restrictions
4

Configure API Key Restrictions

For security, restrict your API key:Application Restrictions:
  • For development: Select HTTP referrers and add http://localhost:*
  • For production (Android): Select Android apps and add your package name and SHA-1 fingerprint
  • For production (iOS): Select iOS apps and add your bundle identifier
API Restrictions:
  • Select Restrict key
  • Enable only:
    • Maps JavaScript API
    • Places API
    • Any other APIs you’re using
Never use unrestricted API keys in production. Always configure application and API restrictions.
5

Set Up Billing

  1. Go to Billing in Google Cloud Console
  2. Link a billing account to your project
  3. Set up budget alerts to monitor usage
Google provides $200 in free monthly credits for Maps Platform. Most development and small-scale apps stay within the free tier.

Application Configuration

Environment Setup

Add your Google Maps API key to the environment files:
export const environment = {
  production: false,
  googleMapsApiKey: 'YOUR_DEVELOPMENT_API_KEY&libraries=places',
  apiUrl: 'http://localhost:3000/api',
  // ... other configuration
};
The &libraries=places parameter loads the Places library automatically. This is required for location autocomplete functionality.

Map Component Configuration

The BaseMapComponent (located at src/app/components/base-map/base-map.component.ts) handles Google Maps initialization:
src/app/components/base-map/base-map.component.ts
import { Component, HostBinding, Input, OnInit } from '@angular/core';
import { GoogleMapsModule } from '@angular/google-maps';
import { environment } from '../../../environments/environment';

@Component({
  selector: 'app-base-map',
  templateUrl: './base-map.component.html',
  styleUrls: ['./base-map.component.scss'],
  standalone: true,
  imports: [GoogleMapsModule],
})
export class BaseMapComponent implements OnInit {
  @Input() height: string | number = '400px';
  @Input() width: string | number = '100%';
  
  // Default map center (Santiago de Cuba)
  center = {
    lat: 20.0217,   // Latitude
    lng: -75.8294   // Longitude
  };
  
  zoom = 14;
  
  // Map configuration options
  mapOptions = {
    apiKey: environment.googleMapsApiKey,
    disableDefaultUI: true,      // Hide default controls
    gestureHandling: 'greedy',   // Allow one-finger panning
    clickableIcons: true         // Enable clicking on POIs
  };
  
  ngOnInit() {
    this.loadGoogleMapsScript();
  }
  
  private loadGoogleMapsScript(): void {
    // Dynamic script loading implementation
    // ...
  }
}

Map Options Reference

The mapOptions object accepts the following configuration:
OptionTypeDefaultDescription
apiKeystringRequiredYour Google Maps API key
disableDefaultUIbooleantrueHide all default UI controls
gestureHandlingstring'greedy'Map gesture behavior ('greedy', 'cooperative', 'none')
clickableIconsbooleantrueAllow clicking on map POIs
mapTypeControlbooleanfalseShow map type control (roadmap, satellite)
zoomControlbooleanfalseShow zoom +/- buttons
streetViewControlbooleanfalseShow street view control
fullscreenControlbooleanfalseShow fullscreen button

Gesture Handling Modes

mapOptions = {
  gestureHandling: 'greedy'
};
  • One-finger pan
  • Two-finger zoom
  • Best for mobile apps
  • Currently used in Rodando Driver

Dynamic Script Loading

The application dynamically loads the Google Maps JavaScript API to optimize performance:
src/app/components/base-map/base-map.component.ts
private loadGoogleMapsScript(): void {
  // Check if Google Maps is already loaded
  if (typeof google !== 'undefined' && google.maps) {
    this.isGoogleMapsLoaded = true;
    return;
  }

  // Check if script is already in DOM
  const existingScript = document.querySelector('script[src*="maps.googleapis.com"]');
  if (existingScript) {
    existingScript.addEventListener('load', () => {
      this.isGoogleMapsLoaded = true;
    });
    return;
  }

  // Create and load the script
  const script = document.createElement('script');
  script.src = `https://maps.googleapis.com/maps/api/js?key=${environment.googleMapsApiKey}&libraries=places`;
  script.async = true;
  script.defer = true;

  script.onload = () => {
    this.isGoogleMapsLoaded = true;
    console.log('Google Maps script loaded successfully');
  };

  script.onerror = () => {
    console.error('Failed to load Google Maps script');
  };

  document.head.appendChild(script);
}
This approach prevents duplicate script loading and handles cases where multiple map components are used.

Using the BaseMapComponent

Incorporate the map component in your pages:
import { BaseMapComponent } from './components/base-map/base-map.component';

@Component({
  selector: 'app-my-page',
  template: `
    <app-base-map 
      [height]="'500px'" 
      [width]="'100%'">
    </app-base-map>
  `,
  imports: [BaseMapComponent],
  standalone: true
})
export class MyPageComponent {}

Component Inputs

InputTypeDefaultDescription
heightstring | number'400px'Map container height
widthstring | number'100%'Map container width

Advanced Configuration

Custom Map Styling

Add custom map styles to match your app’s theme:
mapOptions = {
  apiKey: environment.googleMapsApiKey,
  styles: [
    {
      featureType: 'poi',
      elementType: 'labels',
      stylers: [{ visibility: 'off' }]
    },
    {
      featureType: 'transit',
      elementType: 'labels',
      stylers: [{ visibility: 'off' }]
    }
  ]
};

Enable Additional Controls

mapOptions = {
  apiKey: environment.googleMapsApiKey,
  zoomControl: true,
  zoomControlOptions: {
    position: google.maps.ControlPosition.RIGHT_CENTER
  },
  mapTypeControl: true,
  mapTypeControlOptions: {
    style: google.maps.MapTypeControlStyle.DROPDOWN_MENU,
    position: google.maps.ControlPosition.TOP_RIGHT
  }
};

Set Initial Map Type

mapOptions = {
  apiKey: environment.googleMapsApiKey,
  mapTypeId: 'roadmap' // 'roadmap', 'satellite', 'hybrid', 'terrain'
};

Places Library Integration

The Places library is loaded automatically via the API URL parameter:
script.src = `https://maps.googleapis.com/maps/api/js?key=${apiKey}&libraries=places`;

Using Places Autocomplete

import { } from 'google.maps';

const input = document.getElementById('autocomplete-input') as HTMLInputElement;
const autocomplete = new google.maps.places.Autocomplete(input, {
  types: ['geocode'],
  componentRestrictions: { country: 'cu' } // Restrict to Cuba
});

autocomplete.addListener('place_changed', () => {
  const place = autocomplete.getPlace();
  console.log('Selected place:', place);
});

Dependencies

Ensure you have the Angular Google Maps package installed:
package.json
{
  "dependencies": {
    "@angular/google-maps": "^18.2.14"
  }
}
Install if missing:
npm install @angular/google-maps

Testing Your Configuration

1

Verify API Key

Check that your API key is correctly set in the environment file:
grep googleMapsApiKey src/environments/environment.ts
2

Test in Development

Start the development server:
npm start
Navigate to a page with a map component and check the browser console for errors.
3

Check Network Requests

Open browser DevTools → Network tab and verify:
  • Script loads from maps.googleapis.com
  • No 403 (API key) or 429 (quota) errors
  • Map tiles load successfully
4

Verify Places Library

Open browser console and type:
google.maps.places
Should return an object (not undefined).

Troubleshooting

API Key Errors

Error: “This page can’t load Google Maps correctly” Solutions:
  1. Verify your API key is correct in environment.ts
  2. Check that billing is enabled in Google Cloud Console
  3. Ensure Maps JavaScript API is enabled
  4. Verify API key restrictions allow your domain/app

Quota Exceeded Errors

Error: “You have exceeded your daily request quota” Solutions:
  1. Check usage in Google Cloud Console → APIs & Services → Dashboard
  2. Increase quota limits or enable billing
  3. Implement request caching to reduce API calls
  4. Use map load event listeners to prevent duplicate loads

Map Not Displaying

Symptoms: Gray box instead of map Solutions:
  1. Check browser console for JavaScript errors
  2. Verify the map container has a defined height
  3. Ensure isGoogleMapsLoaded is true before rendering
  4. Check that center coordinates are valid

Places Library Not Loading

Error: “google.maps.places is undefined” Solutions:
  1. Verify &libraries=places is in your API URL
  2. Wait for script load before accessing Places API:
script.onload = () => {
  this.isGoogleMapsLoaded = true;
  // Now safe to use google.maps.places
};

Security Best Practices

Never expose unrestricted API keys in your code or repositories.
1

Use Environment Variables

Store API keys in environment files, not in component code.
2

Configure API Restrictions

Limit API key usage to only required APIs (Maps JavaScript API, Places API).
3

Set Application Restrictions

  • Development: Restrict to localhost
  • Android: Add package name + SHA-1 fingerprint
  • iOS: Add bundle identifier
4

Monitor Usage

Set up billing alerts in Google Cloud Console to catch unusual activity.
5

Use Separate Keys

Use different API keys for development, staging, and production.

Cost Optimization

Free Tier Usage

Google Maps Platform provides:
  • $200 monthly credit
  • 28,000+ map loads per month (free)
  • 100,000+ Places Autocomplete requests (free)

Optimization Tips

  1. Cache map instances - Don’t reload maps unnecessarily
  2. Lazy load - Only load maps when needed (current implementation)
  3. Use static maps - For non-interactive displays
  4. Debounce autocomplete - Reduce Places API calls
  5. Enable billing alerts - Monitor unexpected usage

Next Steps

Environment Config

Learn more about environment variable configuration

Capacitor Setup

Configure Capacitor for native mobile builds

Build docs developers (and LLMs) love