stanley david
stanley david

Reputation: 43

setting google map API key from angular 2 service

Im using sebastine google map in angular 2 application. I know AgmCoreModule.forRoot({ apiKey: "xxxxxxxx" }) can be used to set API key but I need to set API key from a angular service in my @component is it possible....help needed.

Upvotes: 4

Views: 4797

Answers (3)

Mafei
Mafei

Reputation: 3819

you have put the API key in the app.module.ts under the @NgModule and make sure to enable Maps JavaScript API in the google cloud console https://console.cloud.google.com/apis/library/maps-backend.googleapis.com Thanks! enter image description here

@NgModule({
  imports:      [
    BrowserModule,
    FormsModule,
    AgmCoreModule.forRoot({
      // please get your own API key here:
      // https://developers.google.com/maps/documentation/javascript/get-api-key?hl=en
      apiKey: 'API_KEY'
    })
  ],
  declarations: [ AppComponent, HelloComponent ],
  bootstrap:    [ AppComponent ]
})
export class AppModule { }

Upvotes: 0

Fredy
Fredy

Reputation: 11

I added an resolver to get the API key

import { Resolve, ActivatedRouteSnapshot } from '@angular/router'
import { Injectable, Inject } from '@angular/core'
import { SomeService } from '../services/some.service'
import { LazyMapsAPILoaderConfigLiteral, LAZY_MAPS_API_CONFIG } from '@agm/core'
import { Observable, of } from 'rxjs'
import { map, catchError } from 'rxjs/operators'

@Injectable()
export class GoogleMapAPiResolver implements Resolve<boolean> {
    constructor(
        private someService: SomeService,
        @Inject(LAZY_MAPS_API_CONFIG)
        private config: LazyMapsAPILoaderConfigLiteral
    ) {}

    resolve(router: ActivatedRouteSnapshot): Observable<boolean> {
        return this.someService.getGoogleMapApiKey().pipe(
            catchError(error => {
                return of(false)
            }),
            map(response => {
                this.config.apiKey = response
                return true
            })
        )
    }
}

The SomeService consume an endpoint that return the Key

Upvotes: 0

Shivaraj
Shivaraj

Reputation: 613

You may need to update provide a custom provider like this { provide: MapsAPILoader, useClass: CustomLazyAPIKeyLoader } where you have imported AgmCoreModule.

And in CustomLazyAPIKeyLoader class override the load method.

import { Injectable, Inject } from '@angular/core';
import { Http, Response, Headers, RequestOptions } from '@angular/http';
import { MapsAPILoader, LAZY_MAPS_API_CONFIG, LazyMapsAPILoaderConfigLiteral, GoogleMapsScriptProtocol } from 'angular2-google-maps/core';
import { DocumentRef, WindowRef } from 'angular2-google-maps/core/utils/browser-globals';

@Injectable()
export class CustomLazyAPIKeyLoader extends MapsAPILoader {
    private _scriptLoadingPromise: Promise<void>;
    private _config: LazyMapsAPILoaderConfigLiteral;
    private _windowRef: WindowRef;
    private _documentRef: DocumentRef;

    constructor( @Inject(LAZY_MAPS_API_CONFIG) config: any, w: WindowRef, d: DocumentRef, private http: Http) {
        super();
        this._config = config || {};
        this._windowRef = w;
        this._documentRef = d;
    }

    load(): Promise<void> {
        if (this._scriptLoadingPromise) {
            return this._scriptLoadingPromise;
        }

        const script = this._documentRef.getNativeDocument().createElement('script');
        script.type = 'text/javascript';
        script.async = true;
        script.defer = true;
        const callbackName: string = `angular2GoogleMapsLazyMapsAPILoader`;

        this.http.get("getKey")
            .subscribe((res: any) => {
                this._config.apiKey = res._body;
                script.src = this._getScriptSrc(callbackName);
                this._documentRef.getNativeDocument().body.appendChild(script);
            });

        this._scriptLoadingPromise = new Promise<void>((resolve: Function, reject: Function) => {
            (<any>this._windowRef.getNativeWindow())[callbackName] = () => { console.log("loaded"); resolve(); };

            script.onerror = (error: Event) => { reject(error); };
        });

        
        return this._scriptLoadingPromise;
    }

    private _getScriptSrc(callbackName: string): string {
        let protocolType: GoogleMapsScriptProtocol =
            (this._config && this._config.protocol) || GoogleMapsScriptProtocol.HTTPS;
        let protocol: string;

        switch (protocolType) {
            case GoogleMapsScriptProtocol.AUTO:
                protocol = '';
                break;
            case GoogleMapsScriptProtocol.HTTP:
                protocol = 'http:';
                break;
            case GoogleMapsScriptProtocol.HTTPS:
                protocol = 'https:';
                break;
        }

        const hostAndPath: string = this._config.hostAndPath || 'maps.googleapis.com/maps/api/js';
        const queryParams: { [key: string]: string | Array<string> } = {
            v: this._config.apiVersion || '3',
            callback: callbackName,
            key: this._config.apiKey,
            client: this._config.clientId,
            channel: this._config.channel,
            libraries: this._config.libraries,
            region: this._config.region,
            language: this._config.language
        };
        const params: string =
            Object.keys(queryParams)
                .filter((k: string) => queryParams[k] != null)
                .filter((k: string) => {
                    // remove empty arrays
                    return !Array.isArray(queryParams[k]) ||
                        (Array.isArray(queryParams[k]) && queryParams[k].length > 0);
                })
                .map((k: string) => {
                    // join arrays as comma seperated strings
                    let i = queryParams[k];
                    if (Array.isArray(i)) {
                        return { key: k, value: i.join(',') };
                    }
                    return { key: k, value: queryParams[k] };
                })
                .map((entry: { key: string, value: string }) => { return `${entry.key}=${entry.value}`; })
                .join('&');
        return `${protocol}//${hostAndPath}?${params}`;
    }
}

 this.http.get("getKey")
            .subscribe((res: any) => {
                this._config.apiKey = res._body;
                script.src = this._getScriptSrc(callbackName);
                this._documentRef.getNativeDocument().body.appendChild(script);
            });

Above code will make it async.

Upvotes: 2

Related Questions