How do I get latitude and longitude data on the Meteor Server and show on Client like reactive Google Map?


#1

I’m working in a project, in Meteor based on NodeJS, I need create Markers (Places) on the map via Google Maps API. Such “marker” are in a array in the file /server/main.js which has the latitude and longitude of specific places, and it should be returned to /client/main.js and so automatically create such marker on the map.

To create this functionality, I found two tutorials over the Internet.

One of the tutorials, by Meteor Capture, shows how to create a reactive Google Map, which creates the markers based on events, that is click with the left mouse button.

Template.map.onCreated(function() {
    GoogleMaps.ready('map', function(map) {
      google.maps.event.addListener(map.instance, 'click', function(event) {
        Markers.insert({ lat: event.latLng.lat(), lng: event.latLng.lng() });
      });

      var markers = {};

      Markers.find().observe({
        added: function (document) {
          var marker = new google.maps.Marker({
            draggable: true,
            animation: google.maps.Animation.DROP,
            position: new google.maps.LatLng(document.lat, document.lng),
            map: map.instance,
            id: document._id
          });

          google.maps.event.addListener(marker, 'dragend', function(event) {
            Markers.update(marker.id, { $set: { lat: event.latLng.lat(), lng: event.latLng.lng() }});
          });

          markers[document._id] = marker;
        },
        changed: function (newDocument, oldDocument) {
          markers[newDocument._id].setPosition({ lat: newDocument.lat, lng: newDocument.lng });
        },
        removed: function (oldDocument) {
          markers[oldDocument._id].setMap(null);
          google.maps.event.clearInstanceListeners(markers[oldDocument._id]);
          delete markers[oldDocument._id];
        }
      });
    });
  });

The other tutorial, by Stephan van Opstal blog, creates a array in the file /server/main.js

Meteor.startup(function() {
        var data = [
            {
                "name": "Nieuwmarkt, Amsterdam",
                "location": {
                    "type": "Point",
                    "coordinates": {
                        "lat": 52.372466,
                        "lng": 4.900722
                    }
                }
            },
            {
                "name": "Waterlooplein, Amsterdam",
                "location": {
                    "type": "Point",
                    "coordinates": {
                        "lat": 52.368078,
                        "lng": 4.902281
                    }
                }
            },
            {
                "name": "Anne Frank Huis, Amsterdam",
                "location": {
                    "type": "Point",
                    "coordinates": {
                        "lat": 52.375218,
                        "lng": 4.883977
                    }
                }
            },
            {
                "name": "Dappermarkt, Amsterdam",
                "location": {
                    "type": "Point",
                    "coordinates": {
                        "lat": 52.362222,
                        "lng": 4.927778
                    }
                }
            },
            {
                "name": "Westergas, Amsterdam",
                "location": {
                    "type": "Point",
                    "coordinates": {
                        "lat": 52.385946,
                        "lng": 4.875867
                    }
                }
            },
            {
                "name": "Ransdorp, Amsterdam",
                "location": {
                    "type": "Point",
                    "coordinates": {
                        "lat": 52.392954,
                        "lng": 4.993593
                    }
                }
            },
        ];

which has the latitude and longitude specific places, and so returned to /client/main.js But nothing appears on the screen, no marker, neither icon.

GoogleMaps.ready('map', function(map) {
    self.autorun(function() {
        getBox();

        var handle = Meteor.subscribe('places', Session.get('box'));
        if (handle.ready()) {
            var places = Places.find().fetch();

            _.each(places, function(place) {
                var lat = place.location.coordinates[0];
                var lng = place.location.coordinates[1];

                if (!_.contains(lookup, lat+','+lng)) {
                    var marker = new google.maps.Marker({
                        position: new google.maps.LatLng(lat, lng),
                        map: GoogleMaps.maps.map.instance,
                    });
                    lookup.push(lat+','+lng);
                }
            });
        }
    });

    google.maps.event.addListener(map.instance, 'dragend', function(e){
         getBox();
    });

    google.maps.event.addListener(map.instance, 'zoom_changed', function(e){
         getBox();
    });
});

I intend to join both features, thus having a Reactive Google Map to get the latitude and longitude data from server and thus creates the Markers on the map without it being by a event.

Thank you!


#2

To see the complete codes…

  • Here the code by the Meteor Capture tutorial.
  • And here by the Stephan van Opstal blog.

#3

I am doing something similar. I have an unchanging data file that I need to convert into an array then use in my client-side code.

I stored the file in ‘assets’, then on the server at startup I read the file, broke it into lines, then parsed it, storing the results in an array on the server.

Now the problem is how to get the array down to the clients so the clients can use the array…

I can see two possible ways of doing that, but I decided to create a collection with a single record, the content of that record being the whole array.

I then subscribe to the collection when I startup the client and the array becomes accessible. Of course, like any collection, you have to wait for the data to become ‘ready’ (downloaded).

Is that the information you are looking for?


#4

Well, I change my code…
Now the array is setting in client-side, like below:

var list = Offers.find({});

list = [
{
  place: "Teste2",
  offer: "Teste Offer2",
  loc: {
    coordinates: [-50.1681836, -25.0869446]
  }
},
{
  place: "Teste1",
  offer: "Teste Offer1",
  loc: {
    coordinates: [-40.1681836, -20.0869446]
  }
}]; 

And these respective locations must be displayed on the map, each location with its respective marker…

var count = 0;
list.forEach(function(offer) {
 console.log(offer);
  // Animation Timeout
  setTimeout(function() {
    // Create the string into the infowindow
    var contentString = '<p><strong>' + offer.place + '</strong></p>' +
    '<p>' + offer.offer + '</p>';

    // Create the infowindow object
    var infowindow = new google.maps.InfoWindow({
        content: contentString
    });

    // Add the marker on the map
    var marker = new google.maps.Marker({
      position: {lat: offer.loc.coordinates[1], lng: offer.loc.coordinates[0]},
      map: map.instance,
      animation: google.maps.Animation.DROP
    });

    // Add the infowindow for each marker
    marker.addListener('click', function() {
      infowindow.setContent(contentString);
      infowindow.open(map, marker);
    });
  }, count * 200);

  count++;
});

However, just shown is only the first array position (“Teste2”), not all multiple values ​​by “list”.

But I need /server/main.js get these places data from MongoDB, convert in a array and the /client/main.js get this array. And when I startup the client the aray becomes accessible and display it on map!