Vi na edição nº 139 que você está fornecendo a capacidade de acessar o objeto google.maps por meio da função getMap(), que suponho que agora seja a função getNativeMap() no GoogleMapsAPIWrapper. Eu também li que outras pessoas conseguiram fazê-lo funcionar, mas não consigo encontrar nenhuma documentação ou exemplos sobre como usar o GoogleMapsAPIWrapper e o Geocoder.
import { Component, OnInit } from '@angular/core';
import { LocationService } from '../../core/location.service';
import { GoogleMapsAPIWrapper } from 'angular2-google-maps/core';
declare var google: any;
@Component({
selector: 'app-test',
templateUrl: './test.component.html',
styleUrls: ['./test.component.css']
})
export class TestComponent implements OnInit {
constructor(private wrapper: GoogleMapsAPIWrapper) {
this.wrapper.getNativeMap().then((m) => {
console.log("test");
});
}
ngOnInit() {
// var address = "1045 mission street san francisco";
// var geocoder = new google.maps.Geocoder();
// var result = "";
// geocoder.geocode({ 'address': address }, (results, status) => {
// var latitude = results[0].geometry.location.lat();
// var longitude = results[0].geometry.location.lng();
// console.log("lat: " + latitude + ", long: " + longitude);
// });
}
}
No momento, não consigo nem fazer o console.log imprimir "teste". Não tenho certeza por quê. Além disso, a variável m seria o equivalente a google.maps? Para que eu possa usar m.Geocoder()?
Também não tenho certeza se estou importando o GoogleMapsAPIWrapper corretamente. Atualmente estou importando no core.module, pois as diretrizes do Angular 2 dizem que os serviços devem estar no core.module. "sebm-google-map" funciona para mim sem problemas, então acho que o AgmCoreModule foi importado corretamente, só não tenho certeza de como usar o GoogleMapsAPIWrapper.
import {
ModuleWithProviders, NgModule,
Optional, SkipSelf
} from '@angular/core';
import { AgmCoreModule, GoogleMapsAPIWrapper } from 'angular2-google-maps/core';
import { FirebaseService, FirebaseServiceConfig } from './firebase.service';
import { LocationService } from './location.service';
@NgModule({
imports: [AgmCoreModule.forRoot({apiKey: "blahblahapikey"}),],
declarations: [],
exports: [AgmCoreModule],
providers: [FirebaseService, LocationService, GoogleMapsAPIWrapper]
})
export class CoreModule {
constructor( @Optional() @SkipSelf() parentModule: CoreModule) {
if (parentModule) {
throw new Error(
'CoreModule is already loaded. Import it in the AppModule only');
}
}
static forRoot(config: FirebaseServiceConfig): ModuleWithProviders {
return {
ngModule: CoreModule,
providers: [
{ provide: FirebaseServiceConfig, useValue: config }
]
};
}
}
Eu consegui fazer o google.maps.Geocoder() funcionar via GMap do PrimeNG, mas às vezes recebo erros do google não está definido. Então, estou tentando usar o mapa do google de Sebastian.
Se você só precisa de Geocoder(), não precisa usar getNativeMap().
Estou importando MapsAPILoader
, então posso usá-lo desta forma:
this.mapsAPILoader.load().then(() => {
console.log('google script loaded');
var geocoder = new google.maps.Geocoder();
});
Mas se você deseja obter o mapa nativo, seu TestComponent deve ser carregado dentro do componente google map:
<sebm-google-map [latitude]="lat" [longitude]="lng">
<app-test></app-test>
</sebm-google-map>
e você precisa ter certeza de que sua instância do GoogleMapsAPIWrapper dentro de TestComponent
é a mesma instância usada por SebmGoogleMap
@gnujeremie thx pela dica de usar MapsAPILoader. Como faço para importar? Você importou junto com AgmCoreModule?
Não, AgmCoreModule é importado apenas no meu módulo usando o google map.
Eu importo diretamente import { MapsAPILoader } from 'angular2-google-maps/core';
no meu serviço.
Que tal agora -
import { Injectable, NgZone } from '@angular/core';
import { GoogleMapsAPIWrapper } from 'angular2-google-maps/core';
import { MapsAPILoader } from 'angular2-google-maps/core';
import { Observable, Observer } from 'rxjs';
declare var google: any;
@Injectable()
export class GMapsService extends GoogleMapsAPIWrapper{
constructor(private __loader: MapsAPILoader, private __zone: NgZone) {
super(__loader, __zone);
}
getLatLan(address: string) {
console.log('Getting Address - ', address);
let geocoder = new google.maps.Geocoder();
return Observable.create(observer => {
geocoder.geocode( { 'address': address}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
observer.next(results[0].geometry.location);
observer.complete();
} else {
console.log('Error - ', results, ' & Status - ', status);
observer.next({});
observer.complete();
}
});
})
}
}
Além da solução apresentada pelo @vintesh tive que atualizar o lat e lng dentro do NgZone para atualizar o mapa.
clickSearchAddress() {
this._mapsService.getLatLan(this.model.address)
.subscribe(
result => {
// needs to run inside zone to update the map
this._zone.run(() => {
this.model.lat = result.lat();
this.model.lng = result.lng();
});
},
error => console.log(error),
() => console.log('Geocoding completed!')
);
}
Ainda tenho problemas ao tentar usar o geocoder. Aqui está o meu código.
import { MapsAPILoader } from 'angular2-google-maps/core';
constructor(public mapsApiLoader: MapsAPILoader) {
this.mapsApiLoader.load().then(() => {
console.log('google script loaded');
this.geocoder = new google.maps.Geocoder();
console.log(this.geocoder);
});
Recebo dois erros:
Cannot find name 'google'.
e
rollup failed: 'MapsAPILoader' is not exported by node_modules/angular2-google-maps/core/index.js (imported
by src/services/location.ts). For help fixing this error see
https://github.com/rollup/rollup/wiki/Troubleshooting#name-is-not-exported-by-module
@slooker você precisa adicionar declare var google: any;
antes da declaração do seu construtor.
@gnujeremie Isso resolve o problema indefinido do google, mas ainda me diz que MapsAPILoader não é exportado por angular2-google-maps.
@slooker Eu também enfrentei o mesmo problema e o erro MapsAPILoader está chegando porque "node_modules/angular2-google-maps/core/index.js" não exporta MapsAPILoader. Eu resolvi esse problema. Insira o seguinte código no arquivo "node_modules/angular2-google-maps/core/index.js" da seguinte forma:
var core_module_2 = require('./core.umd');
exports.MapsAPILoader = core_module_2.MapsAPILoader;
Isso funciona para mim. Espero que isso funcione para você também.
Vocês tem uma versão funcional? Recebo meus endereços de um banco de dados e preciso de suas coordenadas para construir um cluster de marcadores. GeoCoder é definido no construtor, mas não é acessível pelo método nginit.
VinTesh, por que o serviço que você listou diz que o google é indefinido? Qual é a maneira correta de fazer isso? Obrigado
Estou enfrentando o mesmo problema indefinido do google. Alguma sugestão?
Estou usando "@agm/core": "^1.0.0-beta.0"
Obrigado
getCurrentPositionSuccessCallBack(position: Position) {
const latitude = position.coords.latitude;
const longitude = position.coords.longitude;
const latLng: LatLngLiteral = {
lat: latitude,
lng: longitude
};
const geoCoder = new google.maps.Geocoder();
geoCoder.geocode({ "location": latLng }, (results, status) => {
é meu código e funciona bem, mas estou tentando escrever um teste de unidade
fit('onGeoLocate should set the right location', () => {
spyOn(navigator.geolocation, 'getCurrentPosition').and.callFake(function () {
const position = { coords: { latitude: 32, longitude: -96 } };
arguments[0](position);
});
component.onGeoLocate();
mas falha com
Failed: google is not defined
Ajuda por favor?
Olá amigos do "google indefinido". Já experimentou a dica do nosso colega @gnujeremie?
Isso está funcionando para mim (Angular 2.2.3):
import { Injectable } from '@angular/core';
import { MapsAPILoader } from 'angular2-google-maps/core';
import { Observable } from 'rxjs/Observable';
declare var google: any;
@Injectable()
export class MapsService {
constructor(private __loader: MapsAPILoader) {
}
getGeocoding(address: string) {
return Observable.create(observer => {
try {
//at this point the variable google may be still undefined (google maps scripts still loading)
//so load all the scripts, then...
this.__loader.load().then(() => {
let geocoder = new google.maps.Geocoder();
geocoder.geocode({ address }, (results, status) => {
if (status === google.maps.GeocoderStatus.OK) {
const place = results[0].geometry.location;
observer.next(place);
observer.complete();
} else {
console.error('Error - ', results, ' & Status - ', status);
if (status === google.maps.GeocoderStatus.ZERO_RESULTS) {
observer.error('Address not found!');
}else {
observer.error(status);
}
observer.complete();
}
});
});
} catch (error) {
observer.error('error getGeocoding' + error);
observer.complete();
}
});
}
}
Fabio, você pode fornecer uma amostra de como isso é chamado e usado?
@DoubleExposure supondo que você tenha um construtor como este
construtor(ms privado: MapsService) {
}
você pode chamar isso no seu código
this.ms.getGeocoding( '10 10th Street NE, Atlanta, GA 30309' ).subscribe(function (x) {
console.log(x.toString());
});
@FabioBentoLuiz @gnujeremie Olá, testei seu código e está funcionando muito bem. Exceto a primeira chamada que sempre falha. Eu tentei fazer uma primeira chamada em um ngOnInit mas não parece funcionar.
Aqui minha tentativa de uso
import { Component, OnInit } from '@angular/core';
import { Location } from '@angular/common';
import { Router, ActivatedRoute, ParamMap} from '@angular/router';
import 'rxjs/add/operator/switchMap';
import { Observable } from 'rxjs/Observable';
import { Place } from './../place';
import { PlaceService } from './../place.service';
import { MapsService } from './map.service';
import { AlertService } from './../AlertComponent/alert.service';
@Component({
selector: 'app-detailview',
templateUrl: './detail.component.html',
styleUrls: ['./detail.component.css'],
})
export class DetailComponent implements OnInit {
place: Place;
lat: number = 51.678418;
lng: number = 7.809007;
ngOnInit() {
let selectedId = this.route.paramMap.subscribe(
(params: ParamMap) => this.place = this.placeService.getPlaceById(+params.get('id'))
);
this.maps.getGeocoding('')
.subscribe(
result => console.log(result),
error => console.log(error),
() => console.log('Geocoding completed!')
);
}
constructor(private placeService: PlaceService,
private route : ActivatedRoute,
private location : Location,
private alert : AlertService,
private maps : MapsService) {
}
clickSearchAddress() {
let address = this.place.name + " " + this.place.address + " " + this.place.city + " " + this.place.postalCode;
this.maps.getGeocoding(address)
.subscribe(
result => {
this.lat = result.lat();
this.lng = result.lng();
},
error => console.log(error),
() => console.log('Geocoding completed!')
);
}
back(){
this.location.back();
}
Olá @Canadry ,
Como a primeira chamada falha? Você está usando o MapsAPILoader?
O meu mapa deve centrar-se no endereço.
Então eu mapeei o clickSearchAddress()
em um botão e ele só move o mapa no segundo clique. No primeiro clique só tenho o log : Geocodificação concluída!
Coisa mais estranha, eu coloquei a chamada clickSearchAddress()
na assinatura de route.paramMap
em ngOnInit e lá a função funciona na primeira chamada.
Eu tentei esperar antes de começar a clicar para ter certeza de que o script do mapa do Google está carregado, mas ainda requer dois cliques.
O MapsService usado é aquele que você fornece.
Experimente usando o NgZone conforme descrito aqui
import { NgZone } from '@angular/core';
Adicione ao seu construtor
constructor(private _zone: NgZone){
}
Em seguida, defina lat e lng assim:
this.maps.getGeocoding(address)
.subscribe(
result => {
this._zone.run(() => {
this.lat = result.lat();
this.lng = result.lng();
});
},
error => console.log(error),
() => console.log('Geocoding completed!')
);
Aqui está outro tópico que explica o motivo disso.
Deixe-me saber se funciona.
Parece funcionar, mas não vejo porque.
Obrigado
Consegui trabalhar com agm combinando respostas de @vintesh , @FabioBentoLuiz e @neilpennell.
google-maps.service.ts:
import { Injectable, NgZone } from '@angular/core';
import { GoogleMapsAPIWrapper } from '@agm/core';
import { MapsAPILoader } from '@agm/core';
import { Observable, Observer } from 'rxjs';
declare var google: any;
@Injectable()
export class GMapsService extends GoogleMapsAPIWrapper{
constructor(private __loader: MapsAPILoader, private __zone: NgZone) {
super(__loader, __zone);
}
getLatLan(address: string) {
console.log('Getting Address - ', address);
let geocoder = new google.maps.Geocoder();
return Observable.create(observer => {
geocoder.geocode( { 'address': address}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
observer.next(results[0].geometry.location);
observer.complete();
} else {
console.log('Error - ', results, ' & Status - ', status);
observer.next({});
observer.complete();
}
});
})
}
}
lojas.componente.ts:
import { Component, NgZone } from '@angular/core';
import { GMapsService } from '../services/google-maps.service'
@Component({
templateUrl: 'shops.component.html',
styleUrls: ['shops.component.css']
})
export class ShopsComponent {
constructor(private gMapsService: GMapsService, private __zone: NgZone ){}
lat:number
lng:number
getAddress() {
this.gMapsService.getLatLan('Andorra')
.subscribe(
result => {
this.__zone.run(() => {
this.lat = result.lat();
this.lng = result.lng();
})
},
error => console.log(error),
() => console.log('Geocoding completed!')
);
}
}
lojas.componente.html:
<agm-map [latitude]="lat" [longitude]="lng"></agm-map>
lojas.componente.css:
agm-map {
height: 300px;
}
Obrigado rapazes!
@taneljoeaar você sabe porque estou pegando o google não está definido
em MappingService.getLatLan
Eu principalmente copio e colo seu código.
Muito obrigado.
@beachjf use a solução @FabioBentoLuiz em vez disso, para obter o lat e o long porque a variável "google" pode ainda estar indefinida, pois os scripts do google maps ainda estão sendo carregados. funciona para mim.
Experimentar
importe { GoogleMapsAPIWrapper } de '@agm/core';
em vez de
importe { GoogleMapsAPIWrapper } de 'angular2-google-maps/core';
para o mais recente angular
@taneljoeaar ou tente import { } from 'googlemaps';
em qualquer arquivo em que você está recebendo o erro.
Certifique-se de que os tipos de googlemaps estejam instalados. ( npm install --save @types/googlemaps
)
Bom eu sei que é uma pergunta antiga, mas gostaria de comentar neste tópico um código sobre como pegar os objetos de localização com nome e tipo da cidade, estado e país. Mas, no meu caso, eu estava precisando pegar esses nomes das coordenadas dos usuários. Então, para fazer isso, escrevi isso com base nos últimos comentários:
import {MapsAPILoader} from '@agm/core';
...
constructor(private mapsAPILoader: MapsAPILoader) {
// Get this 'res' from some source, like ionic native geolocation
// Or, for test, create some object like:
let res = {
coords: {
latitude: 40.826514,
longitude: -73.914628
}
}
this.codeLatLng(res.coords);
}
...
codeLatLng(coords) {
this.mapsAPILoader.load().then(() => {
console.log('google script loaded');
let latlng = new google.maps.LatLng({lat: coords.latitude, lng: coords.longitude});
let geocoder = new google.maps.Geocoder();
let location = {
country: null,
state: null,
city: null
};
geocoder.geocode({
'latLng': latlng
}, (results, status) => {
if (status == google.maps.GeocoderStatus.OK) {
if (results[1]) {
for (let i = 0; i < results[0].address_components.length; i++) {
for (let b = 0; b < results[0].address_components[i].types.length; b++) {
if (results[0].address_components[i].types[b] == "country") {
location.country = !location.country ? results[0].address_components[i] : location.country;
} else if (results[0].address_components[i].types[b] == "administrative_area_level_1") {
location.state = !location.state ? results[0].address_components[i] : location.state;
} else if (results[0].address_components[i].types[b] == "administrative_area_level_2") {
location.city = !location.city ? results[0].address_components[i] : location.city;
}
if (location.city && location.state && location.country) {
break;
}
}
}
console.log(location);
} else {
console.log("Results not available");
}
}
else {
console.log("Geocoder failed due to: ", status);
}
});
}
);
}
Para obter os valores das coordenadas, usei a geolocalização nativa iônica.
O código veio de um projeto angular 2+ & Ionic.
Eu implementei o código como você mostra, mas estou recebendo o seguinte erro:
ERRO Erro: StaticInjectorError [MapsAPILoader]:
StaticInjectorError [MapsAPILoader]:
NullInjectorError: Nenhum provedor para MapsAPILoader!
em _NullInjector.get (core.js: 923)
em resolveToken (core.js: 1211)
em tryResolveToken (core.js: 1153)
em StaticInjector.get (core.js: 1024)
em resolveToken (core.js: 1211)
em tryResolveToken (core.js: 1153)
em StaticInjector.get (core.js: 1024)
em resolveNgModuleDep (core.js: 10586)
em _createClass (core.js: 10625)
em _createProviderInstance $ 1 (core.js: 10597)
NOTA: Estou usando Angular 5
Você pode por favor me dar uma mão.
Obrigada.
@ronaldrenteria Você colocou
AgmCoreModule.forRoot({
apiKey: '<YOUR-GOOGLE-API-KEY>'
})
em suas "importações" em app.modules.ts?
Você está usando o LazyLoading?
Esse erro às vezes ocorre quando você esquece de fazer alguma importação ou de fazer todos os requisitos necessários para que a lib funcione.
Você pode obter mais informações nessa página: Angular Maps - Introdução .
Bem, eu quero te dizer, eu já mostrei o mapa e um marcador, mas o que eu quero fazer é converter algumas direções para latitude e longitude, mas isso não foi possível.
Não tenho a importação no app.modules.ts, pois cada componente está usando seu próprio módulo e se estou usando LazyLoading.
Neste caso tenho um componente chamado home.component.ts e este por sua vez tem seu próprio módulo chamado home.module.ts
Antes de usar o MapsAPILoader ele já mostrava o mapa e os marcadores (exemplo colocando a longitude e latitude manualmente), mas agora quero ler os endereços do BD e pegar a longitude latitude.
Obrigada.
maps.service.ts
import { Injectable, NgZone } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';
import 'rxjs/add/observable/throw';
// Manejo de Mapas
import { GoogleMapsAPIWrapper, MapsAPILoader } from '@agm/core';
import { HttpClientModule } from '@angular/common/http';
import { HttpModule } from '@angular/http';
declare var google: any;
@Injectable()
export class MapsService extends GoogleMapsAPIWrapper {
constructor(private __loader: MapsAPILoader, private __zone: NgZone) {
super(__loader, __zone);
}
getLatLan(address: string) {
console.log('Getting Address - ', address);
let geocoder = new google.maps.Geocoder();
return Observable.create(observer => {
geocoder.geocode({ address: address }, function(results, status) {
if (status === google.maps.GeocoderStatus.OK) {
observer.next(results[0].geometry.location);
observer.complete();
} else {
console.log('Error - ', results, ' & Status - ', status);
observer.next({});
observer.complete();
}
});
});
}
}
home.module.ts
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { homeRouting } from './home.routing';
import { SmartadminModule} from '../shared/smartadmin.module';
import { HomeComponent} from './home.component';
// 614iT
import { config_church } from './../shared/churchpro.config';
// Indispensable para manejar los mapas.
import { AgmCoreModule, MapsAPILoader } from '@agm/core';
@NgModule({
imports: [
CommonModule,
homeRouting,
SmartadminModule,
AgmCoreModule.forRoot({
apiKey: config_church.GOOGLE_API_KEY
})
],
declarations: [HomeComponent]
})
export class HomeModule {}
home.component.ts
import { Component, OnInit, NgZone } from '@angular/core';
import { HttpClientModule } from '@angular/common/http';
import { HttpModule } from '@angular/http';
// Mapas
import { MapsService } from '../shared/services/maps.service';
@Component({
selector: 'app-home',
templateUrl: './home.component.html',
styleUrls: []
})
export class HomeComponent implements OnInit {
title: string = 'My first AGM project';
lat: number = 4.6517056;
lng: number = -74.1028404;
zoom: number = 13;
Glat: number;
Glng: number;
constructor(private _mapsService: MapsService, private __zone: NgZone) {}
ngOnInit() {}
getAddress() {
this._mapsService.getLatLan('Andorra').subscribe(result => {
this.__zone.run(() => {
this.Glat = result.lat();
this.Glng = result.lng();
});
}, error => console.log(error), () => console.log('Geocoding completed!'));
}
}
Oi pessoal
Talvez alguém esteja enfrentando um problema semelhante.
Eu preciso customizar a biblioteca AGM, baixei o código e incluí este código como parte do meu projeto, então eu adiciono o agmCoreModule da pasta local src em apps.module, assim.
import { AgmCoreModule } from '../agmLocalModule/core.module';
AgmCoreModule.forRoot({
apiKey: 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
}),
eu tenho uma página com marcadores gerados em um loop ngFor. Mas estou tendo o próximo erro.
```
[longitude]="ubicacion.posicion.longitud"
[markerClickable]="true"
>
```
ERROR Erro: não capturado (em promessa): ReferenceError: o google não está definido
ReferenceError: o google não está definido
em MarkerManager.webpackJsonp.102.MarkerManager.addMarker (marker-manager.ts:82)
em AgmMarker.webpackJsonp.291.AgmMarker.ngOnChanges (marker.ts:169)
Alguma ideia do que poderia ser o problema
Para todos aqueles que estão recebendo o erro 'google is undefined':
use este evento 'mapReady' do elemento agm-map.
" https://angular-maps.com/api-docs/agm-core/components/AgmMap.html#mapReady "
Alguém poderia dar um exemplo funcional?
Exemplo funcional do serviço de geocodificação https://stackblitz.com/edit/angular-google-maps-demo-geocoding com base nos exemplos listados aqui.
Posso chamar mapsAPILoader.load() várias vezes?
oi todo corpo eu tive um pequeno problema, sou novo em AGM e angular também, mas o problema é que eu tenho o place_id, eu queria mudar isso para latlng object era isso, qualquer ajuda é apreciada
@henoktsegaye princípio básico aqui https://developers.google.com/maps/documentation/javascript/examples/geocoding-place-id
então você pode usar o exemplo postado acima, em poucas palavras você precisa de this.geocoder = new google.maps.Geocoder()
e geocoder.geocode({'placeId': placeId}, callbackFunction(results, status))
mas isso será depois que o script for carregado
Este problema foi marcado automaticamente como obsoleto porque não teve atividade recente. Será fechado se não ocorrer mais nenhuma atividade. Obrigado por suas contribuições.
@supruniuk thz DEUS
existe alguma maneira de ter resultado Observable digitado?
@xanscale Por que não, apenas implemente a interface e use-a para verificação de tipos
interface de exportação Localização {
lat: número;
lng: número;
}
@supruniuk quero dizer digitar objetos do google como resultados e status
Como comentário @SainiSK
Para todos aqueles que estão recebendo o erro 'google is undefined':
use este evento 'mapReady' do elemento agm-map.
" https://angular-maps.com/api-docs/agm-core/components/AgmMap.html#mapReady "
Amostra:
(mapReady)="initializedGoogleMapGeocoder($event)"
Comentários muito úteis
Que tal agora -