angular-google-maps

Angular Google Maps Skill

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "angular-google-maps" with this command: npx skills add 7spade/black-tortoise/7spade-black-tortoise-angular-google-maps

Angular Google Maps Skill

Rules

Setup and Configuration

  • Import GoogleMapsModule from @angular/google-maps

  • Load Google Maps script in index.html with API key

  • Use @types/google.maps for TypeScript types

  • Restrict API key by domain/IP for security

Map Component

  • Use <google-map> component with [center] , [zoom] , [options] bindings

  • Set explicit height on google-map element (required for display)

  • Use google.maps.LatLngLiteral type for positions: { lat: number, lng: number }

  • Handle map events: (mapClick) , (mapDrag) , (zoomChanged)

Markers

  • Use <map-marker> component inside <google-map>

  • Set marker properties: [position] , [label] , [title] , [options]

  • Handle marker events: (mapClick) , (mapDragend)

  • Use marker clustering for more than 100 markers

Info Windows

  • Use <map-info-window> component for marker popups

  • Reference info window using @ViewChild(MapInfoWindow)

  • Call infoWindow.open() to display, infoWindow.close() to hide

  • Show info window content conditionally based on selected marker

Drawing Tools

  • Use <map-polygon> for polygon shapes with [paths] and [options]

  • Use <map-polyline> for lines with [path] and [options]

  • Use <map-circle> for circles with [center] , [radius] , [options]

  • Configure styles: fillColor , strokeColor , opacity , strokeWeight

Geocoding

  • Use google.maps.Geocoder for address/coordinate conversion

  • Cache geocoding results to avoid repeated API calls

  • Debounce geocoding requests (300-500ms) for user input

  • Handle geocoding errors gracefully

Performance

  • Lazy load Google Maps script only when needed

  • Use marker clustering for large datasets (>100 markers)

  • Filter markers by viewport bounds

  • NEVER load all markers at once for large datasets

  • NEVER geocode on every keystroke without debouncing

Security

  • NEVER expose API key in client code without restrictions

  • Store API key in environment configuration

  • Enable Google Cloud Console API restrictions (HTTP referrers, API scope)

Context

Summary

Angular Google Maps provides official Angular bindings for Google Maps JavaScript API, enabling declarative map integration with markers, polygons, info windows, and geocoding services.

When to Use This Skill

Activate this skill when you need to:

  • Embed Google Maps in Angular components

  • Add and customize map markers

  • Draw polylines, polygons, and circles

  • Implement info windows and custom overlays

  • Handle map events (click, drag, zoom)

  • Implement marker clustering

  • Add heatmap layers

  • Use Google Maps drawing tools

  • Geocode addresses and reverse geocode coordinates

  • Optimize map performance for large datasets

Installation

npm install @angular/google-maps

Types for TypeScript

npm install @types/google.maps

Setup Steps

Get API Key

  • Go to Google Cloud Console

  • Create or select a project

  • Enable Maps JavaScript API

  • Create API key credentials

  • Restrict API key (recommended)

Load Google Maps Script

<!-- index.html --> <script src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY">&#x3C;/script>

Basic Map Component Example

import { Component } from '@angular/core'; import { GoogleMapsModule } from '@angular/google-maps';

@Component({ selector: 'app-map', standalone: true, imports: [GoogleMapsModule], template: ` <google-map [center]="center" [zoom]="zoom" [options]="options" (mapClick)="onMapClick($event)">

  &#x3C;map-marker 
    *ngFor="let marker of markers"
    [position]="marker.position"
    [label]="marker.label"
    [title]="marker.title"
    (mapClick)="onMarkerClick(marker)">
  &#x3C;/map-marker>
&#x3C;/google-map>

, styles: [ google-map { height: 400px; width: 100%; } `] }) export class MapComponent { center: google.maps.LatLngLiteral = { lat: 25.033, lng: 121.565 }; // Taipei zoom = 12;

options: google.maps.MapOptions = { mapTypeId: 'roadmap', disableDefaultUI: false, zoomControl: true, scrollwheel: true };

markers: Marker[] = [ { position: { lat: 25.033, lng: 121.565 }, label: 'A', title: 'Taipei 101' } ];

onMapClick(event: google.maps.MapMouseEvent) { if (event.latLng) { const newMarker = { position: event.latLng.toJSON(), label: String.fromCharCode(65 + this.markers.length), title: 'New Location' }; this.markers.push(newMarker); } }

onMarkerClick(marker: Marker) { console.log('Marker clicked:', marker); } }

interface Marker { position: google.maps.LatLngLiteral; label?: string; title?: string; }

Map with Info Window Example

@Component({ template: ` <google-map [center]="center" [zoom]="zoom"> <map-marker *ngFor="let marker of markers" [position]="marker.position" (mapClick)="openInfo(marker, infoWindow)"> </map-marker>

  &#x3C;map-info-window #infoWindow>
    &#x3C;div *ngIf="selectedMarker">
      &#x3C;h3>{{ selectedMarker.title }}&#x3C;/h3>
      &#x3C;p>{{ selectedMarker.description }}&#x3C;/p>
    &#x3C;/div>
  &#x3C;/map-info-window>
&#x3C;/google-map>

` }) export class MapWithInfoComponent { @ViewChild(MapInfoWindow) infoWindow!: MapInfoWindow; selectedMarker: any;

openInfo(marker: any, infoWindow: MapInfoWindow) { this.selectedMarker = marker; infoWindow.open(); } }

Marker Clustering Example

import { MarkerClusterer } from '@googlemaps/markerclusterer';

@Component({ template: &#x3C;google-map #map [center]="center" [zoom]="zoom"> &#x3C;map-marker *ngFor="let marker of markers" [position]="marker.position"> &#x3C;/map-marker> &#x3C;/google-map> }) export class ClusteredMapComponent implements AfterViewInit { @ViewChild('map') mapComponent!: GoogleMap; markers: Marker[] = [];

ngAfterViewInit() { if (this.mapComponent.googleMap) { const markerClusterer = new MarkerClusterer({ map: this.mapComponent.googleMap, markers: this.getGoogleMarkers() }); } }

private getGoogleMarkers(): google.maps.Marker[] { return this.markers.map(m => new google.maps.Marker({ position: m.position }) ); } }

Drawing Tools Example

@Component({ template: ` <google-map [center]="center" [zoom]="zoom"> <map-polygon [paths]="polygonPaths" [options]="polygonOptions"> </map-polygon>

  &#x3C;map-polyline 
    [path]="polylinePath"
    [options]="polylineOptions">
  &#x3C;/map-polyline>
  
  &#x3C;map-circle 
    [center]="circleCenter"
    [radius]="circleRadius"
    [options]="circleOptions">
  &#x3C;/map-circle>
&#x3C;/google-map>

` }) export class DrawingMapComponent { polygonPaths: google.maps.LatLngLiteral[] = [ { lat: 25.033, lng: 121.565 }, { lat: 25.035, lng: 121.567 }, { lat: 25.031, lng: 121.569 } ];

polygonOptions: google.maps.PolygonOptions = { fillColor: '#FF0000', fillOpacity: 0.3, strokeColor: '#FF0000', strokeOpacity: 1, strokeWeight: 2 };

polylinePath: google.maps.LatLngLiteral[] = [ { lat: 25.030, lng: 121.560 }, { lat: 25.035, lng: 121.565 } ];

polylineOptions: google.maps.PolylineOptions = { strokeColor: '#0000FF', strokeOpacity: 1.0, strokeWeight: 3 };

circleCenter: google.maps.LatLngLiteral = { lat: 25.033, lng: 121.565 }; circleRadius = 1000; // meters

circleOptions: google.maps.CircleOptions = { fillColor: '#00FF00', fillOpacity: 0.2, strokeColor: '#00FF00', strokeOpacity: 0.8, strokeWeight: 2 }; }

Geocoding Service Example

import { Injectable } from '@angular/core'; import { Observable, from } from 'rxjs'; import { map } from 'rxjs/operators';

@Injectable({ providedIn: 'root' }) export class GeocodingService { private geocoder = new google.maps.Geocoder();

geocodeAddress(address: string): Observable<google.maps.LatLngLiteral | null> { return from( this.geocoder.geocode({ address }) ).pipe( map(response => { if (response.results && response.results[0]) { const location = response.results[0].geometry.location; return { lat: location.lat(), lng: location.lng() }; } return null; }) ); }

reverseGeocode(location: google.maps.LatLngLiteral): Observable<string | null> { return from( this.geocoder.geocode({ location }) ).pipe( map(response => { if (response.results && response.results[0]) { return response.results[0].formatted_address; } return null; }) ); } }

References

  • Angular Google Maps Documentation

  • Google Maps JavaScript API

  • MarkerClusterer

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

material-design-3

No summary provided by upstream source.

Repository SourceNeeds Review
General

architecture-ddd

No summary provided by upstream source.

Repository SourceNeeds Review
General

webapp-testing

No summary provided by upstream source.

Repository SourceNeeds Review
General

angular-material-cdk-animations

No summary provided by upstream source.

Repository SourceNeeds Review