I recently got started with ng2. So I created a project using angular-cli, then I realized I need some third party modules. Such as Google maps api, lodash, jquery...etc. I know the basics of Typescript, but how do I use these modules in an Angular2 app? Also, I want to use just the library, for example Google maps api, not any existing ng2 module/component someone else made ontop of the Google maps api - For the sake of learning.
Previously, with just JS I would include the js file and reference the api documentation to know which methods to reference and build my app. Now with Angular2, what steps should I take to do the same?
From my research it looks like I first install the type script files needed.
so for Google maps I did npm install --save @types/google-maps.
Now, do I need to import this module into my angular app by including it in app.module.ts? In the imports array? Or is it now globally available?
One source mentioned installing it with npm and in my angular-cli.json including a reference to that library in the scripts array. like so:
"scripts": ['./node_modules/googlemaps/googemaps.min.js'],
Which method to use in installing the google maps api? I would think Typescript might be the way to go since the rest of the Angular app is going to be written in Typescript.
Now in my app.component.ts, I want to create a simple map using the typescript I installed. How would I do so? The google maps api says to create a new instance of the map like so.
var map = new google.maps.Map(document.getElementById('map'), {
center: {lat: -34.397, lng: 150.644},
scrollwheel: false,
zoom: 8
});
How would I do that with the typescript version of Googlemaps I just installed?
Would a typescript version of Googlemaps have all the same methods as the original API? Do typescripts of popular JS libraries have a documentation site I can reference?
The agm project pointed by @Steve G. give a good starting point, but for some reason (like manage your own request policy) you may want to make your own typed wrapper. Here how I did it with Angular Cli :
First step :
npm i --save @types/googlemaps
Secondly add the types to your tsconfig.app.json :
"types": ["googlemaps"]
Finally write your typescript :
//nothing to import here
//Replace this by anything without an ID_KEY
const getScriptSrc = (callbackName) => {
return `https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&callback=${callbackName}`;
}
export class GMapService {
private map: google.maps.Map;
private geocoder: google.maps.Geocoder;
private scriptLoadingPromise: Promise<void>;
constructor() {
//Loading script
this.loadScriptLoadingPromise();
//Loading other components
this.onReady().then(() => {
this.geocoder = new google.maps.Geocoder();
});
}
onReady(): Promise<void> {
return this.scriptLoadingPromise;
}
initMap(mapHtmlElement: HTMLElement, options: google.maps.MapOptions): Promise<google.maps.Map> {
return this.onReady().then(() => {
return this.map = new google.maps.Map(mapHtmlElement, options);
});
}
private loadScriptLoadingPromise() {
const script = window.document.createElement('script');
script.type = 'text/javascript';
script.async = true;
script.defer = true;
const callbackName: string = 'UNIQUE_NAME_HERE';
script.src = getScriptSrc(callbackName);
this.scriptLoadingPromise = new Promise<void>((resolve: Function, reject: Function) => {
(<any>window)[callbackName] = () => { resolve(); };
script.onerror = (error: Event) => { reject(error); };
});
window.document.body.appendChild(script);
}
/** Exemple of wrapped to promise API */
geocode(address: string | google.maps.GeocoderRequest): Promise<google.maps.GeocoderResult[]> {
return this.onReady().then(() => {
this.geocoder.geocode(typeof address == "google.maps.GeocoderRequest" ? address: {address: address},
(results: google.maps.GeocoderResult[], status: google.maps.GeocoderStatus) => {
if(status == google.maps.GeocoderStatus.OK) {
return results;
} else {
throw new Error(status.toString());
}
});
});
});
}
And so your map component will look like this :
@Component({
selector: 'app-gmap-wrapper',
template: '<div #map style="width:400px; height:300px">loading...</div>'
})
export class GMapWrapperComponent implements OnInit {
@ViewChild('map') mapRef: ElementRef;
constructor(private gmapService: GMapService) { }
ngOnInit() {
this.gmapService.initMap(this.mapRef.nativeElement, {
center: {lat: 1234.1234, lng: 1234.1234},
scrollwheel: true,
zoom: 8
});
}
}
This code should be better without the namespace google.maps in prefix of all types. Maybe any suggestion ?
I also had troubles with AGM in componets, then i tried nu-maps and also there I had troubles.
So I used plain google api javascript and I think its better: https://cloud.google.com/maps-platform/?hl=de