I try to display projects according to a slider (range, with noUislider). The names of the projects are displayed reactively, depending on the cursor.
Now… i want to do the same thing with a bunch of googlemap markers. When I move the cursor , I want to see the markers change on the map (googlemapJs API)
Reactive list of projets :
Template.body.helpers({
projects: function() {
var slider = Session.get("slider"); //get the range values
return Projects.find({
endDate: {
$gte: slider[0],
$lt: slider[1]
}
});
}
});
Way I currently display markers after loading the map :
Template.body.onCreated(function() {
GoogleMaps.ready('atlasArchi', function(map) {
var projectsArray = Projects.find().fetch();
var marker, i;
for (i = 0; i < projectsArray.Length; i++) {
marker = new google.maps.Marker({
position: new google.maps.LatLng(projectsArray[i]['lat'], projectsArray[i]['lng']),
map: map.instance
});
}
});
});
So, i guess i can’t use Template.body.onCreated for displaying the markers.
How can i use Template.body.helpers to make my list of markers reactive ?
It Seems to work after some changes.
The markers still don’t appear in real time. But it works in the console, the array is updated . So I just have to figure out how to remove markers on the map, when that are not in the array.
Thank you very much !
code :
Tracker.autorun(function() {
var slider = Session.get("slider"); //get the range values
projectsArray = Projects.find({
endDate: {
$gte: slider[0],
$lt: slider[1]
}
}).fetch(); //must be an array ? i think
console.log(projectsArray);
var projNumber = projectsArray.length;
var marker, i;
for (i = 0; i < projNumber; i++) {
marker = new google.maps.Marker({
position: new google.maps.LatLng(projectsArray[i]['lat'], projectsArray[i]['lng']),
map: map.instance
});
}
});
Use observe instead of fetch, see http://docs.meteor.com/#/full/observe
Just add a marker on added and store it in an array. Remove it on removed event.
Template.body.onCreated(function() {
GoogleMaps.ready('atlasArchi', function(map) {
Tracker.autorun(function() {
var slider = Session.get("slider"); //get the range values
var projectsList = Projects.find({
endDate: {
$gte: slider[0],
$lt: slider[1]
}
});
var markers = {};
projectsList.observe({
added: function(document) {
var marker = new google.maps.Marker({
animation: google.maps.Animation.DROP,
position: new google.maps.LatLng(document.lat, document.lng),
map: map.instance,
id: document._id
});
markers[document._id] = marker;
},
removed: function(oldDocument) {
markers[oldDocument._id].setMap(null);
google.maps.event.clearInstanceListeners(markers[oldDocument._id]);
delete markers[oldDocument._id];
}
});
});
});
});
I can see that it works through animation of markers. When i move noUislider, new markers are falling down.
But, the wrong markers are staying on the map. I’ll try to figure it out.
When i write a console.log(oldDocument); in the removed event, nothing happens. The “removed” event is not called when projectsList is changing.
I tried… same result.
The “removed” event is never called. But the “called” event works every time I move the slider.
I don’t now why… i’m trying to find examples. People seem to use observe() and removed…
Maybe my query does not change the right way ? ^^
Or maybe the removed event is never called because I didn’t specified something in the query.
Maybe an idea… but i’m not sure.
When i move the slider, session values are changing a lot. So, my query is changing a lot. Then maybe the callback “removed” is not called. http://img15.hostingpics.net/pics/431978added.jpg
So I tried to modify the slider function :
Template.slider.rendered = function() {
this.$("#slider").noUiSlider({
start: Session.get("slider"),
connect: true,
animate: true,
step: 1,
range: {
'min': rangeStartDate,
'max': rangeEndDate
},
format: wNumb({
decimals: 0
})
}).on('slide', function(ev, val) {
// set real values on 'slide' event
//Session.set('slider', val); I DELETED THIS LINE
}).on('change', function(ev, val) {
// round off values on 'change' event
Session.set('slider', [Math.round(val[0]), Math.round(val[1])]);
});
};
After removing the line above…
Nothing changes , I don’t understand why the " observe" function does not see changes on the query. Even if i have only one change in my query when i move the slider.
Thank you,
I guess publish and subscribe are my last chance… I’m stuck on this problem. What do you mean by “ie” ?
I tried a lot of things today, but nothing works (old markers are staying on the map).
When i move the slider, it is as if a new group of projects were included in my query. But the “old documents” are not accessible.
I would like to understand exactly how observe() works, but i can’t find this kind of documentation.
Maybe the problem is changing values in the query like i do, with $gte and $lt.
As for you old markers, when you check your collection in the browser after changing the slider, does it have the same number of documents? or just more documents?
Even though you can observe a cursor at any time, I believe for what you want to accomplish you need to use the callback from your subscribe and do something like documented in the docs.
When i change the slider, i can see some markers falling down on the map (googlemap marker’s animation).
The markers that fall on the map correspond to the projects that are part of the range. So if i change the slider, i can see 2 projects falling, 10 projects, 4 projects… etc It’s good.
The only problem is that the markers don’t fade when projects are no longer part of the range. And I saw on the console that the callback “removed” was never called.
If I initialize the map with a small slider, and gradually increases the range , the projects appear gradually. There is a problem for the other way.
Sorry, I’m rewriting the app with node.js, socket.io and maybe react to interact with googlemap. I did not start the front-end…
I was tired of several problems with Meteor (outdated dependencies , no npm, hidden complexity, front end, deployment on a VPS!!). I want something transparent that is not “magic”.
It should not be too difficult to send data to the client (markers) with socket.io.
Some people advised me to adopt redux or similar technology in order to “prerender” react on the server, but it gets complicated for me… Can I just use React with the node router or this is incoherent ?