-
-
Save msaxena25/fa59c2130642de3ef6330c6cff2ce6c2 to your computer and use it in GitHub Desktop.
#Create a CustomLazyAPIKeyLoader class file and extends MapsAPILoader | |
import { GoogleMapsScriptProtocol, LAZY_MAPS_API_CONFIG, LazyMapsAPILoaderConfigLiteral, MapsAPILoader } from '@agm/core'; | |
import { DocumentRef, WindowRef } from '@agm/core/utils/browser-globals'; | |
import { Inject, Injectable } from '@angular/core'; | |
import { AppGlobals } from './../../Common/Services/app.global'; | |
@Injectable() | |
export class CustomLazyAPIKeyLoader extends MapsAPILoader { | |
private _scriptLoadingPromise: Promise; | |
private _config: LazyMapsAPILoaderConfigLiteral; | |
private _windowRef: WindowRef; | |
private _documentRef: DocumentRef; | |
constructor(@Inject(LAZY_MAPS_API_CONFIG) config: any, w: WindowRef, d: DocumentRef, private appGobal: AppGlobals) { | |
super(); | |
this._config = config || {}; | |
this._windowRef = w; | |
this._documentRef = d; | |
} | |
load(): Promise { | |
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`; | |
// You can hit an http request to get key by http.get method. | |
// Here I have already loaded that key before and saved in global service file and used here... | |
let key = this.appGobal.googleApiKey; // GET OUR KEY FROM YourAPI.json API -- | |
console.log('map key', key); | |
this._config.apiKey = key; | |
script.src = this._getScriptSrc(callbackName); | |
this._documentRef.getNativeDocument().body.appendChild(script); | |
this._scriptLoadingPromise = new Promise((resolve: Function, reject: Function) => { | |
(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 } = { | |
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}`; | |
} | |
} | |
#2: Add above file in app.modules.ts file : | |
import { CustomLazyAPIKeyLoader } from './Services/custom-apikey-loader.service'; | |
// And Add in providers config like : | |
{ provide: MapsAPILoader, useClass: CustomLazyAPIKeyLoader } |
How did you inject AsyncMapsConfigService into the loader?
I either get an error that the compilter can't resolve it or during runtime that settingObservable$ is a property of undefined.
And even if i don't use any services and just have my own BehaviourSubject as observable i get an error in super.load().
`import { LAZY_MAPS_API_CONFIG, LazyMapsAPILoader } from '@agm/core';
import { DocumentRef, WindowRef } from '@agm/core/utils/browser-globals';
import { Inject, Injectable } from '@angular/core';
import { map } from 'rxjs/operators';
import { BehaviorSubject } from 'rxjs';
export class AsyncMapsConfigService {
private setting$ = new BehaviorSubject({ apiKey: '' })
get settingObservable$() {
setTimeout(resp => this.setting$.next({ apiKey: 'myKey' }), 500)
return this.setting$.asObservable()
}
}
@Injectable()
export class CustomLazyMapsAPILoader extends LazyMapsAPILoader {
constructor(@Inject(LAZY_MAPS_API_CONFIG) config: any, w: WindowRef, d: DocumentRef, private asyncMapsConfigService: AsyncMapsConfigService) {
super(config, w, d);
this.asyncMapsConfigService = new AsyncMapsConfigService()
}
load(): Promise<any> {
if (this._scriptLoadingPromise) {
return this._scriptLoadingPromise;
}
this.asyncMapsConfigService.settingObservable$.pipe(
map(result => {
console.log(result)
this._config.apiKey = result.apiKey;
return super.load();
})
).toPromise();
}
}`
It can be done with much less code