Skip to content

feat(google-maps): geocoder wrapper #21665

@dmitry-stepanenko

Description

@dmitry-stepanenko

Feature Description

Currently there's no way wrapper for geocoder API. Although it's functionality seems pretty straightforward, recently I've faced an issue when geocoder's callback wasn't picked properly by Angular. It caused an issue, that was hard to identify.

Below I'm posting the preliminary implementation of Geocoder, I would like to be present. If needed, I can create a PR with this feature and corresponding tests.

import { Injectable, NgZone } from "@angular/core";
import { GoogleMapsModule } from "google-maps-module";
import { Observable } from "rxjs";

/**
 * Angular service that wraps `google.maps.Geocoder` instance to send geocode requests to Google servers.
 * 
 * @see https://developers.google.com/maps/documentation/javascript/reference/geocoder
 */
@Injectable({
    providedIn: GoogleMapsModule
})
export class Geocoder implements google.maps.Geocoder {
    /**
     * The underlying google.maps.Geocoder object
     *
     * @see https://developers.google.com/maps/documentation/javascript/reference/geocoder#Geocoder
     */
    private readonly _geocoder = new google.maps.Geocoder();

    constructor(private _ngZone: NgZone) { }

    /**
     * Wrapper for `geocode` request, that is being sent to Google servers. 
     * @see https://developers.google.com/maps/documentation/javascript/reference/geocoder#Geocoder.geocode
     * 
     * @returns the list of `GeocoderResult`s. 
     */
    geocode(request: google.maps.GeocoderRequest): Observable<google.maps.GeocoderResult[]> {
        return new Observable<google.maps.GeocoderResult[]>((observer) => {
            this._geocoder.geocode(request, (results, status) => {
                // need to manually trigger ngZone because "geocode" callback is not picked up properly by Angular
                this._ngZone.run(() => {
                    if (status === google.maps.GeocoderStatus.OK) {
                        // if status is "OK", the response contains a valid GeocoderResponse.
                        observer.next(results);
                        observer.complete();
                    } else {
                        observer.error(status);
                    }
                });
            });
        });
    }
}

Use Case

It can be used as follows in "Angular" way with observables:

@Component({...})
export class SomeComponent {
  constructor(private geocoder: Geocoder) {}

  getAddressPosition(address: google.maps.GeocoderRequest['address']): Observable<google.maps.LatLng> {
    return this.geocoder.geocode({ address }).pipe(map(results => results[0].geometry.location))
  }
}

Metadata

Metadata

Assignees

Labels

P4A relatively minor issue that is not relevant to core functionsarea: google-mapsfeatureThis issue represents a new feature or feature request rather than a bug or bug fix

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions