9

How is it possible to load an external js file, from a url in an Angular component?

To be specific, I'm trying to load google-maps-api to my angular project. Currently, I'm doing it in my index.html like this:

<script async defer src="https://maps.googleapis.com/maps/api/js?key=API_KEY&callback=initMap">
</script>

Note: I'm aware of angular-maps. That's not an option.

2 Answers 2

14

You can use Promise to load google API asynchronously whenever you want.

// map-loader.service.ts
import ...
declare var window: any;

@Injectable()
export class MapLoader {

    private static promise;
    map: google.maps.Map;

    public static load() {
        if (!MapLoader.promise) { // load once
            MapLoader.promise = new Promise((resolve) => {
                window['__onGapiLoaded'] = (ev) => {
                    console.log('gapi loaded')
                    resolve(window.gapi);
                }
                console.log('loading..')
                const node = document.createElement('script');
                node.src = 'https://maps.googleapis.com/maps/api/js?key=<YOUR _API_KEY>&callback=__onGapiLoaded';
                node.type = 'text/javascript';
                document.getElementsByTagName('head')[0].appendChild(node);
            });
        }

        return MapLoader.promise;
    }

    initMap(gmapElement, lat, lng) {

        return MapLoader.load().then((gapi) => {
            this.map = new google.maps.Map(gmapElement.nativeElement, {
                center: new google.maps.LatLng(lat, lng),
                zoom: 12
            });
        });
    }
}

Component

//maps.component.ts

...
@Component({
  selector: 'maps-page',
  templateUrl: './maps.component.html'
})
export class MapsComponent implements OnInit {       

  @ViewChild('gmap') gmapElement: any;
  constructor(public mapLoader: MapLoader) { }

  ngOnInit() {

      this.mapLoader.initMap(this.gmapElement, -37.81, 144.96)  // await until gapi load
  }

  ...
}

Component HTML

// maps.component.html
<div #gmap ></div>

Don't forget to add CSS to the element.

Sign up to request clarification or add additional context in comments.

9 Comments

I'm not sure why this answer wasn't upvoted. I got my solution by looking at this code -- but I implemented in app.component.ts in ngOnInit(). Cheers!
replace "map: google.maps.Map;" with "map: any;" to prevent type errors. also add "window." before any "google.maps."
@desmati, it is to use @types/googlemaps in typescript. It will support auto-completion of google API. If you have an error, you may install @types/googlemaps.
The main answer doesn't work for me but this works, only add to your css by id: #map { height: 100vh; width: 100vw; } Then add to node.src variable: node.src +='&key=YOUR_KEY';
I presumed the person need this code, also know about CSS. Regarding key, google changed their policy and need API key. I will update the above code.
|
7

A solution is to create the script tag dynamically in ngAfterViewInit()

import { DOCUMENT } from '@angular/common';
...

constructor(private @Inject(DOCUMENT) document, 
            private elementRef:ElementRef) {};

ngAfterViewInit() {
  var s = this.document.createElement("script");
  s.type = "text/javascript";
  s.src = "https://maps.googleapis.com/maps/api/js?key=API_KEY";
  this.elementRef.nativeElement.appendChild(s);
}

See also https://github.com/angular/angular/issues/4903

Update

<div id="map" #mapRef></div>

export class GoogleComponent implements OnInit {
  @ViewChild("mapRef") mapRef: ElementRef;
  constructor() { }

  ngOnInit() {
    this.showMap();
  }

  showMap() {
    console.log(this.mapRef.nativeElement);
    const location = { lat: 28.5355, lng: 77.3910 };
    var options = {
      center: location,
      zoom: 8
    }

    const map = new google.maps.Map(this.mapRef.nativeElement, options);
    this.addMarket(map, location);
  }
  addMarket(pos, map) {
    return new google.maps.Marker({
      position: pos,
      map: map,
    });
  }
}

7 Comments

Thanks for the answer. But what about the callback part? How can i get notified when api is ready?
Thanks again, but the above code doesn't wait for google.maps to be loaded.
It will load once the js is loaded
Can you explain how? I'm confused.
@HamidAsghari : check out this link for working demo stackblitz.com/edit/…
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.