When using Meteor 0.8.0, how do you update a flot chart when new data arrives? I looked at the example at Meteor-flot, but it is updating with fake data via a timer on the page. and not reactive data coming from a collection.
So far I have something like:
// returns an object with a label and an array of timestamp, value
// like { label:'test', data:[[1397605016000, 1332],[1397605616000,1356],[1397606216000,1380]]}
Template.example.helpers({
readings: function(){
DataReadings.find();
}
});
Template.example.rendered = function() {
$.plot ($("#flot"), [this.data.data], {
series: {
lines: {
show: true
},
points: {
show: true
}
},
xaxis: {
mode: 'time',
timeformat: '%H:%M'
}
});
};
This works great for the initial render, but not sure how to go about updating the chart once new data arrives, which is about once every five minutes. So how to call the plot.setData(newData) & plot.draw() when new data arrives?
One way to do it is using a cursor/collection observer. I'm using this method in my Meteor app to update a Flot chart and it works great.
After your initial plot creation in Template.example.rendered function, add a cursor observer that updates your chart anytime a new document is added (or removed) on the collection:
// Subscribe to collection (or no need to do this if it's already done on your route)
Meteor.subscribe('dataReadings', someFilterVarOrNot);
// Add a cursor observer for all documents added with a date greater
// than right now (uses moment.js)
// (If you don't do this, you'll get an "added" fire for every document
// that's ALREADY been added - not sure why it does this but it does
dataReadingsObserveHandle = DataReadings.find({
createdAt: {$gte: moment().toDate()}}).observe({
// Fires anytime a new document is added
added: function(dataReading) {
$('#flot').data("plot").setData(dataReading.data);
$('#flot').data("plot").draw();
// Or setup whatever query/calculation you need to assemble a
// new data set for your chart, there are also some other observers like
// observeChanges() which let you see how a document has changed versus
// being added or removed
},
// Fires anytime a document is removed
removed: function(removedDataReading) {
// Update and redraw chart like above...
}
});
The dataReadingsObserveHandle is intentionally global so you can destroy it later because apparently a collection observer is server intensive. This doesn't necessarily have to be global if you have scope access to it wherever it would need to be destroyed:
// Once your chart no longer needs to be updated call...
dataReadingsObserveHandle.stop();
dataReadingsObserveHandle = null;
I believe when a user navigates to a different template and is no longer looking at your chart, the observer automatically gets destroyed. See http://docs.meteor.com/#observe for more information.
I would love to hear about other methods to do this using ReactiveVar or Deps.dependency. Especially if they're more efficient
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With