Google maps latitude returning undefined

Whenever i run the console.log(lat) the value i get returned is undefined - I have the suspicion that it’s because the data from the collection RegisteredStorage hasn’t been fetched yet by the time the code is processed ? however I check for the subscription to be ready in the template before running placeMarkers.

Meteor.startup(function() {
GoogleMaps.load();
});

Template.Map.helpers({

exampleMapOptions: function() {
    // Make sure the maps API has loaded
    if (GoogleMaps.loaded()) {


        // Map initialization options
        return {
            center: new google.maps.LatLng(-37.8136, 144.9631),
            zoom: 8
        };

    }
},

placeMarkers: function(){

    var Users =  RegisterStorage.find({"Space":22}).fetch();

    GoogleMaps.ready('exampleMap', function(map) {
        // Add a marker to the map once it's ready

        var k;

        for(k in Users){


            result = Users[k].Address;
            var lat = Meteor.call("getLat", result);
            var long = Meteor.call("getLong", result);


            var marker = new google.maps.Marker({
                position: new google.maps.LatLng(lat,long),
                map: map.instance

            });

        }

    });

Template.Map.onCreated(function() {

this.subscribe("storage");


});

`

Meteor Methods

    Meteor.methods({
getLat: function(Address){
    var geo = new GeoCoder();
    var result = geo.geocode(Address);
    console.log(result[0].latitude);

    return result[0].latitude;

},

getLong: function(Address){
    var geo = new GeoCoder();
    var result = geo.geocode(Address);
    console.log(result[0].longitude);

    return result[0].longitude;

}
})` 

Template :smile:

<template name="Map">
    <div class="map-container">
    {{#if Template.subscriptionsReady}}
        {{> googleMap name="exampleMap" options=exampleMapOptions}}
            {{placeMarkers}}
    {{/if}}
    </div>
</template>

Btw, the console.log in the methods provide the correct coordinates however

Did you ever resolve this? I’m having an issue converting an address to lat/long for DB storage and am trying to figure out how to achieve this.

yea i managed to fix it To convert the address to lat long i recommend using Geocoder

Collections :

Address: {
    type: String,
    label: "Address",
    optional: true

},
Long:{

    type: String,
    label: 'longitude',
    optional: true,
    autoValue:function(){

        return Meteor.call('GetLong',this.siblingField("Address").value);
    },
    autoform: {
        type: "hidden",
        label: false
    }


}

Methods

GetLong: function (Address) {

	var geo = new GeoCoder();
	var Future = Npm.require('fibers/future');

	// make some new future
	var fut = new Future();
	var message = geo.geocode(Address);


	fut.return(message[0].latitude.toString());

	// wait for something from the future
	return fut.wait();
}
1 Like

Interesting solution. I like your use of a method which appears to run on the server-side. I implemented a client-side solution, which would require processing before DB entry. I’ll probably be using your solution instead to ensure data integrity.

  // Activate geocomplete on #main-test
  Template.test.onRendered(function() {
      this.autorun(function() {
         // Wait for API to be loaded
         if (GoogleMaps.loaded()) {
            $('#location').geocomplete({
               details: 'form',
               detailsAttribute: 'data-geo'
            });
         }
      });
  });
1 Like

I’m glad you made it work ! Hope you solution helps in case you decide to change your approach !

can i ask what does $(’#location’) reference in your code ? I’m new to javascript/meteor

The location ID is a form field that supports Google’s Places API for autocomplete. Here’s the HTML associated (it’s quite crude but works for a proof-of-concept)…

<form>
   <input type="text" name="geolocate" placeholder="Enter an address" id="location">
   <input type="text" id="lat" data-geo='lat' value="">
   <input type="text" id="lng" data-geo='lng' value="">
</form>
1 Like

I noticed in your method, you’re retrieving a longitude, yet the code appears to be latitude. The address is being geocoded in var message but you’ll returning one parameter. I’m trying to get both long and lat back for storage and want it done in one method.

oh lol, thanks for pointing that out :smiley: i hadn’t noticed

well, I use two different methods in mine…getLong and getLat… I’m sure you can do it a different way o.O don’t ask me how tho !

GetLong: function (Address) {

	var geo = new GeoCoder();
	var Future = Npm.require('fibers/future');

	// make some new future
	var fut = new Future();
	var message = geo.geocode(Address);


	fut.return(message[0].latitude.toString());

	// wait for something from the future
	return fut.wait();
},


GetLat: function (Address) {

	var geo = new GeoCoder();
	var Future = Npm.require('fibers/future');

	// make some new future
	var fut = new Future();
	var message = geo.geocode(Address);


	fut.return(message[0].longitude.toString());

	// wait for something from the future
	return fut.wait();
}

Collection:

Lat:{

    type: String,
    label:'latitude',
    optional: true,
    autoValue:function(){
        return Meteor.call('GetLat',this.siblingField("Address").value);
    },
    autoform: {
        type: "hidden",
        label: false
    }




},

Long:{

    type: String,
    label: 'longitude',
    optional: true,
    autoValue:function(){

        return Meteor.call('GetLong',this.siblingField("Address").value);
    },
    autoform: {
        type: "hidden",
        label: false
    }


},

I guess you could return the object " var message " instead of the lat and long coordinates

Yup, that’s what I’m implementing. It would still require 2 separate geocoding requests and I don’t think they get cached. This is a hit to the load time.

I’m actually unsure what would be the most appropriate method since I’m also new to Meteor. Maybe using a hook?

AutoForm.addHooks(['locationForm', 'anotherForm'], {
   // Confirmation messages
   onSuccess: function(operation, result, template) {
      FlashMessages.sendSuccess('Success!');
      // Router.go("/success");
   },
   // Populated the createdBy for DB
   formToDoc: function(doc) {
      // MAGIC HERE
     var geoCode = GetGeo(doc.address);
     doc.long = geoCode[0];
     doc.lat = geoCode[1]; 
      // Associate the user ID with the form
      doc.createdBy = Meteor.userId();
      return doc
   },
});

A few notes about this…

  1. I haven’t tested it
  2. It runs client side
  3. We might as well just use the places API to give us the lat/long if using autocomplete. This would fill 2 hidden fields as cited earlier: Google maps latitude returning undefined