11

Hi I am trying to implement google maps api in angular. It was pretty simple in angularjs but I cant figure out whats not working. I have a simple app which is showing products along with their location. Upon clicking location the location does show on map. But to shop map I am using google maps. I have done quite much. But this error is keep coming.

google is not defined

app.component.ts

    import { Component } from '@angular/core';
import { Observable } from 'rxjs/Rx';
import { ProductService } from './product.service';
declare var google: any;

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
  providers: [ProductService]
})
export class AppComponent {

  //define an array of products
  products = [];

  //constructor func
  constructor(private _productService: ProductService) { }

  //after constructor func this func runs , in which we are
  // accessing the class function getproducts and objects products
  // through this.
  // => means callback in which we are dumping data in products
  //array
  ngOnInit() {
    this._productService.getProducts()
      .subscribe(products => { this.products = products[0].data; console.log(this.products); })

    var map;
    map = new google.maps.Map(document.getElementById('map'), {
      center: { lat: -34.397, lng: 150.644 },
      zoom: 8
    });

  }

}

Index.html

    <!doctype html>
<html lang="en">

<head>
  <meta charset="utf-8">
  <title>Shopober</title>
  <base href="/">

  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="icon" type="image/x-icon" href="favicon.ico">
</head>

<body>
  <app-root></app-root>
  <script src="https://maps.googleapis.com/maps/api/js?key=xxxxx" async defer>


  </script>
</body>

</html>

app.component.html

 <table id="products">
    <tr>
      <th>Id</th>
      <th>Product Name</th>
      <th>Price</th>
      <th>In Stock</th>
      <th>Location</th>
      <th>Image</th>
    </tr>
    <tr *ngFor="let product of products">
      <td>{{product.id}}</td>
      <td>{{product.product_name}}</td>
      <td>{{product.product_price}}</td>
      <td>{{product.product_stock}}</td>
      <td>
        <a>{{product.location[0].lat + ',' + product.location[0].lng}}</a>
      </td>
      <td>{{product.product_image}}</td>
    </tr>
  </table>

6 Answers 6

16

You have to wait the view initialization before loading the google maps script. You can do it with the AfterViewInit hook, like this :

import {AfterViewInit, Component} from '@angular/core';
...
export class YourComponent implements AfterViewInit {

  ngAfterViewInit(): void {
    // Load google maps script after view init
    const DSLScript = document.createElement('script');
    DSLScript.src = 'https://maps.googleapis.com/maps/api/js?key=xxxxx'; // replace by your API key
    DSLScript.type = 'text/javascript';
    document.body.appendChild(DSLScript);
    document.body.removeChild(DSLScript);
  }
Sign up to request clarification or add additional context in comments.

9 Comments

You want me to make another ts file and write this code ? Or can i do this in my app.comp.ts
Add it in the component that contain the google maps code!
Cannot find name 'AfterViewInit'.
same error. I did it something like this export class Appcomponent implement AfterViewInit { products = []; constructor(private _productService: ProductService) { } ...... Your code }
Yes, it's the normal behavior of google maps, you have to set a fixed height in px, or resize the container too. Check this thread fot that : stackoverflow.com/questions/10209704/…
|
2

Removing the async and defer attributes worked for me, but not sure it's wise to do keeping performance aspect of the website in mind.

so your script tag should look like:

<script src="https://maps.googleapis.com/maps/api/js?key=xxxxx">

Comments

1

It looks like your components load before the google script. There is a great angular2+ plugin for google maps : https://github.com/SebastianM/angular-google-maps

Did you check it out ? It allows you to do all the common stuff with google maps, and avoid the common loading and other errors.

4 Comments

i know this plugin but i dont want to use it
I'm not sure if suggesting a plugin without some additional explanations is a good answering practice.
Yeah, you're probably true. I'll add some details, sorry !
NOT a great plugin - in my opinion. I have encountered numerous bugs. Rather use the "google-map" that is now built into angular.
1

Other way similar @Boulboulouboule solution

import {AfterViewInit, Component} from '@angular/core';
...
export class YourComponent implements AfterViewInit {

  constructor(private httpClient: HttpClient) {}

  ngAfterViewInit(): void {
    this.httpClient.jsonp('https://maps.googleapis.com/maps/api/js?key=xxxxx', 
      'callback')
      .pipe(
         map(() => true),
         catchError(() => of(false)),
      );
    }

}

Comments

0

Trying implementing -

import GoogleMaps from 'google-maps';

After importing google-maps use below code:

GoogleMaps.KEY = <your map api key>;
GoogleMaps.load((google) => {
  // place your code here
});

1 Comment

dont want to use any plugin. Please explain with respect to orignal maps api
-1

Try wrapping the initialization inside a setTimeout() function like below:

ngOnInit(){
 setTimeout(()=> {
 // Put the logic here 


 }, 1000);
}

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.