Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

You have included the Google Maps API multiple times on this page #692

Closed
escarabin opened this issue Oct 2, 2016 · 20 comments
Closed

You have included the Google Maps API multiple times on this page #692

escarabin opened this issue Oct 2, 2016 · 20 comments

Comments

@escarabin
Copy link

escarabin commented Oct 2, 2016

I know this issue happened to others but I am pretty stuck with it since days, can't find any solution.

Here is my @NgModule:

import { NgModule } from '@angular/core';
import { AgmCoreModule } from 'angular2-google-maps/core/index';

// Global vars
import appGlobals = require('./../globals');

@NgModule({
    imports:      [ AgmCoreModule.forRoot({
                        apiKey: appGlobals.googleMapsApiKey
                    }) ],
})

export class JobSearchModule {}

Here is my HTML:

<div class="col-md-12 google-maps-container">
        <sebm-google-map [latitude]="mapLat"
                         [longitude]="mapLng"
                         [mapDraggable]="false"
                         [zoom]="zoom"
                         [zoomControl]="false"
                         [streetViewControl]="false"
                         (mapClick)="mapClicked($event)">
            <sebm-google-map-marker [latitude]="mapLat"
                                    [longitude]="mapLng">

            </sebm-google-map-marker>
        </sebm-google-map>
    </div>

And here is a screenshot of what I have inside my HTML head tag:

screen shot 2016-10-02 at 13 36 15

So it looks like it is really including the API twice but I don't know why or how.

@sebholstein
Copy link
Owner

@escarabin the problem is that you import the module in a child module of your app. You have to import it inside your root module of the app. Closing this as this is no bug. Feel free to reopen. Thx!

@escarabin
Copy link
Author

escarabin commented Oct 26, 2016

hey @SebastianM! Thanks for the advice but I am still facing the issue.
Here is my configuration:

  • I need to use the angular2-google-maps in a child module calledjob-search-module.ts
  • I have ashared.module.ts which contains all of the components and modules that I use in several other modules.
  • My root module is app.module.ts

Now, when I import AgmCoreModule in my app.module.ts, I see an error saying that sebm-google-mapis not a part of my job-search-module.ts and no map is shown.
When I import AgmCoreModule either in shared.module.ts or in job-search.module.ts, I see "You have included the Google Maps API multiple times on this page".

What should I do then?

PS: I do not have the ability to re-open the issue

@escarabin
Copy link
Author

anyone? :( I am quite stuck with it right now

@EddyP23
Copy link

EddyP23 commented Nov 3, 2016

@escarabin i had similar problem. Try this.

You need to import maps in the root application module, so you do something like this:

@NgModule({
    declarations: [
        ...
    ],
    imports: [
        ...,
        AgmCoreModule.forRoot({
            apiKey: 'some key here'
        })
    ],

But then if you want to use maps in a component that does not belong to this module, go to that module and do this:

@NgModule({
    declarations: [
        SomeComponentThatHasMapsInItsHtml,
        .....
    ],
    imports: [
        AgmCoreModule,
        ...
    ],

@EddyP23
Copy link

EddyP23 commented Nov 3, 2016

To add why I think this works, is because you need to register the thing at the root of your application (so that google stuff is initialised with your key).

But you are using <seb-maps-smth-smth> in a component that belongs to another module, so you need to add the AgmCoreModule as an import so that it can find an exported component in this module that has selector seb-maps-smth-smth .

Hope that solves the issue

@escarabin
Copy link
Author

escarabin commented Nov 4, 2016

Thank you so much for the effort @EddyP23 but unfortunately I still see the error...is it really working on your side using angular2-google-maps@0.15.0? It's very weird.

The problem is not the error itself but it also causes a bunch of completely random bugs on the page...

Also, you are talking about <seb-maps-smth-smth>. I don't use this tag and I don't see it in the docs. I'm using <sebm-google-map>

@EddyP23
Copy link

EddyP23 commented Nov 4, 2016

@escarabin Yes, I am using version 0.15.0.

By smth smth I do mean any seb-maps-{placeholder} selector. My Html looks like:

<sebm-google-map #sebmGoogleMap
        [latitude]="myVar1"
        [longitude]="myVar2"
        (idle)='onIdle()'
        [zoom]='mapZoomLevel'
        [streetViewControl]='false'
        >
            <sebm-google-map-marker #marker
                [latitude]="myVar3"
                [longitude]="myVar4"
                ></sebm-google-map-marker>
    </sebm-google-map>

What error are you seeing now? I do believe this setup should work. Could you share more code?

@escarabin
Copy link
Author

escarabin commented Nov 4, 2016

I still see "You have included the Google Maps API multiple times on this page" error.

My HTML looks like this:

<sebm-google-map #sebmGoogleMap
                         [latitude]="mapLat"
                         [longitude]="mapLng"
                         [mapDraggable]="false"
                         [zoom]="zoom"
                         [zoomControl]="false"
                         [streetViewControl]="false"
                         (mapClick)="mapClicked($event)">
            <sebm-google-map-marker [latitude]="mapLat"
                                    [longitude]="mapLng">

            </sebm-google-map-marker>
</sebm-google-map>

Here is my child module:

import { NgModule } from '@angular/core';
import { jobSearchRouting } from './job-search.routes';
import { SharedModule }   from './../shared/shared.module';
import { AgmCoreModule } from 'angular2-google-maps/core/index';

// Components
import { SearchComponent } from './components/search.component';

@NgModule({
    declarations: [ SearchComponent ],
    imports:      [ jobSearchRouting,
                    AgmCoreModule,
                    SharedModule ]
})

export class JobSearchModule {}

and my app.module.ts @NgModule:

@NgModule({
    declarations: [ AppComponent,
                    HomeComponent,
                    HeaderComponent,
                    FooterComponent,
                    PostComponent,
                    ClubComponent,
                    CandidateSignUpComponent,
                    PostPreviewComponent,
                    SignInComponent,
                    ProfileSubHeaderComponent,
                    RecruiterPromoComponent,
                    NotificationsComponent ],
    imports:      [ RouterModule,
                    HttpModule,
                    SharedModule,
                    BrowserModule,
                    AgmCoreModule.forRoot({
                        apiKey: appGlobals.googleMapsApiKey
                    }),
                    MetaModule.forRoot(metaConfig),
                    routing ],
    providers:    [ NotificationsService,
                    MetaService ],
    bootstrap:    [ AppComponent ],
})

@EddyP23
Copy link

EddyP23 commented Nov 4, 2016

Hm.. That is weird. Are you sure you don't have script tags importing google maps anywhere (e.g. in index.html) the old way? Something like this:

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

I would also go through all the usages of AgmCoreModule to check that you are not importing it twice in some other place accidentally.

@onocy
Copy link

onocy commented Jul 12, 2017

I'm also having this issue. I've added the AgmCoreModule.forRoot({...}) in the app.module for my components, and I've checked for multiple google api calls.
Still returns the same error.

@jasperSpeicher
Copy link

I am also having this issue. I've also added the AgmCoreModule.forRoot({...}) in the app.module for my components, and I've also checked for multiple google api calls.

@jasperSpeicher
Copy link

Ok my mistake, if it helps anyone else here--try deleting your old script tag rather than commenting it out. For some reason, commenting it in the template was not removing it.

@gerajc
Copy link

gerajc commented Jul 15, 2017

@EddyP23 , What can i do if im using skd autocomplete and agm maps?
Since it imports into index <script async defer src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&callback=initMap">
</script>

@agillesp
Copy link

agillesp commented Aug 2, 2017

Unfortunately I cannot just delete your old script tag because we have some legacy parts of our app that require the script tag being present. I'd suggest the lazy loader check if the api lib is present first before fetching. I'm kinda stuck right now and have to probably edit the source.

@agillesp
Copy link

agillesp commented Aug 2, 2017

Below is my fairly nasty hack to allow for a) older dependencies that assume the api is included statically via a hardcoded <script src="" tag remain functioning and b) avoiding the You have included the Google Maps API multiple times on this page error.

Implement the Overrides

import { ModuleWithProviders } from '@angular/core';
import { AgmCoreModule } from '@agm/core';
import { MapsAPILoader } from '@agm/core/services/maps-api-loader/maps-api-loader';
import { LazyMapsAPILoaderConfigLiteral } from '@agm/core/services/maps-api-loader/lazy-maps-api-loader';

export class AgmCoreOverrideModule {
    static forRoot(lazyMapsAPILoaderConfig?: LazyMapsAPILoaderConfigLiteral): ModuleWithProviders {
        var module = AgmCoreModule.forRoot(lazyMapsAPILoaderConfig);

        // This is the magical path to what we need to override.
        // Future releases of Agm Core may totally break this.
        let provider: any = module.providers[2];
        provider.useClass = IgnoreIncludingApiLoader;

        return module;
    }
}

export class IgnoreIncludingApiLoader extends MapsAPILoader {
    load(): Promise<void> {
        // Do absolutely nothing.
        return new Promise<void>(resolve => resolve());
    }
}

Wire it up in app.module

@NgModule({
    imports: [
        AgmCoreOverrideModule.forRoot({
            apiKey: '<key>'  // Not really needed.
        })
    ],
    ...

sebholstein pushed a commit that referenced this issue Dec 2, 2017
Check in lazy loader if google maps script was loaded and maps are initialized in window.

Fixes #692
@astuppad
Copy link

astuppad commented Feb 1, 2018

I have been trying to resolve this issue from many days finally i arrived at the solution by comparing all the module file in the project.
Please check for all the modules in your package.
If you find the below code in multiple modules delete them and keep it only in one module.

platformBrowserDynamic().bootstrapModule(AppModule)
.catch(err => console.log(err));

Its better to keep only in main.ts
Hope this solution helps you guys

@Juliete
Copy link

Juliete commented Mar 19, 2018

I was able to resolve the problem in the escenario that @escarabin describes overriding the module.

import { ModuleWithProviders, Inject, Optional, NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { AgmCoreModule, LAZY_MAPS_API_CONFIG, MapsAPILoader } from '@agm/core';
import { LazyMapsAPILoader, LazyMapsAPILoaderConfigLiteral } from '@agm/core/services/maps-api-loader/lazy-maps-api-loader';
import { WindowRef, DocumentRef, BROWSER_GLOBALS_PROVIDERS } from '@agm/core/utils/browser-globals';



@NgModule({ imports: [CommonModule, AgmCoreModule], exports: [AgmCoreModule]})
export class AgmOverrideModule {
  static forRoot(lazyMapsAPILoaderConfig?: LazyMapsAPILoaderConfigLiteral): ModuleWithProviders {
    return {
      ngModule: AgmOverrideModule, providers: [BROWSER_GLOBALS_PROVIDERS, { provide: MapsAPILoader, useClass: ApiLoader },
        { provide: LAZY_MAPS_API_CONFIG, useValue: lazyMapsAPILoaderConfig } ]}
  }
}

export class ApiLoader extends LazyMapsAPILoader {
  private static cargado: boolean;
  constructor( @Optional() @Inject(LAZY_MAPS_API_CONFIG) config: any, @Inject(WindowRef) w: WindowRef, @Inject(DocumentRef)  d: DocumentRef) {
    super(config, w, d);
    
  }
  load(): Promise<void> {
    if (ApiLoader.cargado) {
      return new Promise<void>(resolve => resolve());
    } else {
      return new Promise<void>((resolve, reject) => {
        super.load()
          .then(() => {
            ApiLoader.cargado = true;
            resolve();
          })
          .catch(err => {
            reject(err);
          });
      });
    }
  }
}

And importing the module in the shared module

@NgModule({
  imports: [
...
    AgmOverrideModule.forRoot({
      apiKey: environment.claveMaps
    }),
...
export class ComunModule

And in the lazy loaded module

@NgModule({
  imports: [
    ComunModule,
    AgmOverrideModule,
    ...
  ]

@astuppad
Copy link

astuppad commented Mar 20, 2018 via email

@templth
Copy link

templth commented Oct 1, 2018

I also have the problem with version 1.0.0-beta.5 of the library. I investigated the problem and it doesn't occur in every case.

Here is the context, I have the main module that uses AgmCoreModule.forRoot:

@NgModule({
  imports: [
    (...)
    AgmCoreModule.forRoot({
      apiKey: environment.googleMaps.apiKey
    }),

and a lazy module that uses AgmCoreModule:

@NgModule({
  declarations: [
    (...)
  ],
  imports: [
    (...)
    AgmCoreModule,

I can reproduce the problem when first going to a page linked to the root module and then going to a page of the lay module. If I go directly to the page whithin the lazy module, I don't have the problem...

I investigated a bit the problem and i appeared that the load method of the LayLoader of agm is called twice in this case in parallel:

  • one from the FitBoundsService
function FitBoundsService(loader) {
        var _this = this;
        this._boundsChangeSampleTime$ = new BehaviorSubject(200);
        this._includeInBounds$ = new BehaviorSubject(new Map());
        this.bounds$ = from(loader.load()).pipe(flatMap(function () { return _this._includeInBounds$; }), sample(this._boundsChangeSampleTime$.pipe(switchMap(function (time) { return timer(0, time); }))), map(function (includeInBounds) { return _this._generateBounds(includeInBounds); }), shareReplay(1));
    }
  • one from the GoogleMapsAPIWrapper
GoogleMapsAPIWrapper.prototype.createMap = function (el, mapOptions) {
        var _this = this;
        return this._zone.runOutsideAngular(function () {
            return _this._loader.load().then(function () {
                var map = new google.maps.Map(el, mapOptions);
                _this._mapResolver(map);
                return;
            });
        });
    };

Do you have an idea of how to fix this problem?
Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests